当前位置: 首页 > news >正文

SpringBoot学习日记 Day5:解锁企业级开发核心技能

一、前言:从玩具项目到生产系统

经过前四天的学习,我们已经能够开发基础功能了。但要让应用真正具备生产价值,还需要掌握数据库高级操作、事务控制、缓存优化等企业级开发技能。今天就来攻克这些关键知识点!

二、JPA进阶:让数据库操作更高效

1. 复杂查询的三种实现方式

方式一:方法名派生查询

public interface UserRepository extends JpaRepository<User, Long> {// 根据姓名模糊查询+年龄范围List<User> findByUsernameContainingAndAgeBetween(String name, Integer minAge, Integer maxAge);// 统计大于某年龄的用户数Long countByAgeGreaterThan(Integer age);
}

方式二:@Query注解(JPQL)

@Query("SELECT u FROM User u WHERE u.dept.id = :deptId AND u.status = :status")
List<User> findUsersByDeptAndStatus(@Param("deptId") Long deptId, @Param("status") Integer status);

方式三:原生SQL查询

@Query(value = "SELECT * FROM users WHERE reg_time > :date", nativeQuery = true)
List<User> findRecentUsers(@Param("date") Date date);

2. 分页查询最佳实践

@GetMapping("/users")
public PageResult<User> getUsers(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer size,@RequestParam(required = false) String name) {Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createTime").descending());Page<User> userPage;if (StringUtils.isEmpty(name)) {userPage = userRepository.findAll(pageable);} else {userPage = userRepository.findByUsernameContaining(name, pageable);}return PageResult.success(userPage);
}

3. 关联关系实战(用户-部门示例)

实体类配置:

@Entity
@Data
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;@ManyToOne@JoinColumn(name = "dept_id")private Department department;
}@Entity
@Data
public class Department {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@OneToMany(mappedBy = "department")private List<User> users;
}

查询优化建议:

1. 使用@EntityGraph解决N+1查询问题:

@EntityGraph(attributePaths = {"department"})
List<User> findAllWithDepartment();

2. 延迟加载时注意事务范围:

// 在Service层方法上添加事务注解
@Transactional(readOnly = true)
public User getUserDetail(Long id) {User user = userRepository.findById(id).orElseThrow();// 此时可以安全访问延迟加载的关联对象System.out.println(user.getDepartment().getName());return user;
}

三、事务管理:数据一致性的守护者

1. 声明式事务基础

@Service
@RequiredArgsConstructor
public class OrderService {private final OrderRepository orderRepository;private final UserRepository userRepository;@Transactionalpublic void createOrder(OrderDTO dto) {// 扣减用户余额User user = userRepository.findById(dto.getUserId()).orElseThrow(() -> new BusinessException("用户不存在"));user.setBalance(user.getBalance() - dto.getAmount());userRepository.save(user);// 创建订单Order order = new Order();// 设置订单属性...orderRepository.save(order);// 如果这里抛出异常,上面所有操作都会回滚}
}

2. 事务传播行为实验

传播行为说明适用场景
REQUIRED(默认)当前有事务则加入,没有则新建大多数业务方法
REQUIRES_NEW总是新建事务,挂起当前事务日志记录等独立操作
NESTED在当前事务嵌套子事务部分需要独立回滚的子流程

测试用例:

@Transactional
public void parentMethod() {// 操作1...childMethod();  // 测试不同传播行为// 操作2...
}@Transactional(propagation = Propagation.REQUIRES_NEW)
public void childMethod() {// 子方法操作...
}

四、Redis缓存:性能加速器

1. 集成Redis三步走

第一步:添加依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

第二步:配置连接

spring:redis:host: localhostport: 6379password: database: 0

第三步:启用缓存

@SpringBootApplication
@EnableCaching
public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args);}
}

2. 缓存注解实战

@Service
public class UserService {// 缓存查询结果@Cacheable(value = "user", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElseThrow();}// 更新时清除缓存@CacheEvict(value = "user", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}// 条件缓存@Cacheable(value = "user", key = "#name", unless = "#result == null")public User getUserByName(String name) {return userRepository.findByUsername(name);}
}

五、文件操作:用户头像上传实战

1. 配置文件上传

spring:servlet:multipart:max-file-size: 2MBmax-request-size: 10MB

2. 实现上传接口

@PostMapping("/avatar/upload")
public Result<String> uploadAvatar(@RequestParam("file") MultipartFile file) {if (file.isEmpty()) {throw new BusinessException("请选择文件");}// 生成唯一文件名String fileName = UUID.randomUUID() + "." + FileUtil.getExtension(file.getOriginalFilename());// 保存文件Path path = Paths.get("uploads/avatars", fileName);try {Files.createDirectories(path.getParent());file.transferTo(path);} catch (IOException e) {throw new BusinessException("文件上传失败");}return Result.success("/avatars/" + fileName);
}

3. 文件下载实现

@GetMapping("/avatar/download/{filename:.+}")
public void downloadAvatar(@PathVariable String filename, HttpServletResponse response) throws IOException {Path path = Paths.get("uploads/avatars", filename);if (!Files.exists(path)) {response.sendError(404, "文件不存在");return;}response.setContentType("image/jpeg");Files.copy(path, response.getOutputStream());
}

六、今日成果:用户管理系统升级版

1. 数据库层:

   - 实现多表关联查询

   - 支持分页排序

   - 完善事务管理

2. 缓存层:

   - 高频查询结果缓存

   - 自动更新缓存策略

3. 文件操作:

   - 头像上传下载功能

   - 文件大小限制处理

4. API增强:

// 分页查询示例
GET /users?page=1&size=10&name=张&sort=age,desc// 头像上传
POST /avatar/upload// 带缓存的用户查询
GET /users/{id}

七、避坑指南

1. N+1查询问题:

   - 使用@EntityGraph或JOIN FETCH优化

   - 测试时开启SQL日志观察查询次数

2. 事务失效场景:

   - 方法必须是public

   - 自调用问题(AOP失效)

   - 异常类型默认只回滚RuntimeException

3. 缓存一致性:

   - 更新数据库后及时清除缓存

   - 考虑使用@CachePut更新缓存

4. 文件存储安全:

   - 校验文件类型(不要仅靠扩展名)

   - 限制上传目录权限

   - 考虑使用云存储服务

八、明日计划

1. 学习SpringBoot定时任务

2. 集成邮件发送功能

3. 实现系统监控端点

4. 探索AOP统一日志处理

思考题:在电商系统中,下单操作需要扣减库存、生成订单、扣减优惠券等多个步骤,该如何设计事务边界?欢迎评论区分享你的设计方案!

如果觉得这篇日记有帮助,请点赞收藏支持~完整代码示例可通过私信获取。在实际开发中遇到问题也欢迎留言讨论!

http://www.lryc.cn/news/612802.html

相关文章:

  • 90-基于Flask的中国博物馆数据可视化分析系统
  • 8- 知识图谱 — 应用案例怎么 “落地” 才有效?构建流程与行业实践全解析
  • LoRaWAN的网络拓扑
  • Kong vs. NGINX:从反向代理到云原生网关的全景对比
  • PCL提取平面上的圆形凸台特征
  • 阿里系bx_et加密分析
  • 构造函数:C++对象初始化的核心机制
  • 天猫商品评论API技术指南
  • uni-app X能成为下一个Flutter吗?
  • Flutter报错...Unsupported class file major version 65
  • C# 异步编程(async_await特性的结构)
  • PyTorch 核心三件套:Tensor、Module、Autograd
  • `/dev/vdb` 是一个新挂载的 4TB 硬盘,但目前尚未对其进行分区和格式化。
  • vscode 打开设置
  • Flutter 三棵树
  • 【物联网】基于树莓派的物联网开发【25】——树莓派安装Grafana与Influxdb无缝集成
  • CentOS 7 下通过 Anaconda3 运行llm大模型、deepseek大模型的完整指南
  • 人工智能的20大应用
  • 从Centos 9 Stream 版本切换到 Rocky Linux 9
  • 360纳米AI、实在Agent、CrewAI与AutoGen……浅析多智能体协作系统
  • 构建在 OpenTelemetry eBPF 基础之上:详解 Grafana Beyla 2.5 新特性
  • 【0基础3ds Max】菜单栏介绍
  • 多模态融合(Multimodal Fusion)
  • PCIe Base Specification解析(九)
  • mapbox进阶,mapbox-gl-draw绘图插件扩展,绘制新增、编辑模式支持点、线、面的捕捉
  • 什么是SpringBoot
  • Shuffle SOAR使用学习经验
  • Q-Learning详解:从理论到实践的全面解析
  • 扎根国际数字影像产业园:共享空间助力企业高效发展
  • 施耐德 Easy Altivar ATV310 变频器:高效电机控制的理想选择(含快速调试步骤及常见故障代码)