返回专题首页

Java 专题

数据访问实践:JDBC、事务、MyBatis、JPA 与连接池

Java 后端项目几乎绕不开数据库,但数据访问真正难的地方,从来不只是“能不能查到数据”,而是下面这些问题怎样被同时管住:

Java 专题第 16 篇 / 26 篇5 分钟

Java 后端项目几乎绕不开数据库,但数据访问真正难的地方,从来不只是“能不能查到数据”,而是下面这些问题怎样被同时管住:

  • 事务边界怎么划;
  • 性能怎样稳定;
  • 对象和表结构怎样映射;
  • 什么时候该用 SQL 直写;
  • 什么时候该交给框架抽象;
  • 连接资源怎样不被打爆。

所以数据访问不是某个 DAO 层技巧,而是一条非常核心的系统主线。很多服务端项目真正变乱,往往就是从数据库访问边界开始的。

为什么数据访问不是“会用 ORM 就够了”?

因为数据库层真正要回答的,不只是“把数据存进去”,而是:

  • 这组操作是否必须保持一致;
  • 查询控制力到底要多强;
  • 业务是否更适合模型驱动还是 SQL 驱动;
  • 性能和可维护性怎样平衡;
  • 出了慢查询、锁等待、连接耗尽时,问题从哪层排查。

如果这些问题都没被想清楚,团队很容易会在数据层里进入几种混乱状态:

  • 一部分人喜欢直写 SQL,一部分人喜欢全 ORM;
  • 事务边界全靠感觉;
  • 连接池参数默认到底;
  • Repository、Mapper、Service 职责越来越模糊;
  • 性能问题一出现,就开始怀疑数据库“太慢”。

所以数据访问的关键从来不是某个框架本身,而是整体边界有没有被设计清楚。

JDBC、事务、连接池、MyBatis、JPA 这几层该怎么分?

更稳的理解方式是把它们看成不同抽象层级:

  • JDBC 是最底层的数据库访问接口;
  • 事务负责保证一组操作的一致性;
  • 连接池负责复用连接和控制资源;
  • MyBatis 更偏 SQL 可控和映射灵活;
  • JPA 更偏对象模型和实体关系抽象。

它们不是互相替代,而是站在不同高度解决问题。很多团队之所以会把数据层做乱,往往就是因为把这些层混成了一团,最后既想要 ORM 的便捷,又想要 SQL 的绝对控制,还想让事务和连接池自动替自己兜底。

事务为什么首先是业务边界问题?

很多人学事务时,会先记:

  • 开启事务;
  • 提交;
  • 回滚;
  • 传播行为;
  • 隔离级别。

这些当然重要,但更底层的问题其实是:哪些操作在业务上必须被视为一个整体?

比如:

  • 创建文章并关联标签,是否必须一起成功;
  • 支付成功后更新订单和积分,是否允许部分成功;
  • 删除用户时,关联清理应该同步完成还是异步完成。

所以事务首先是业务边界问题,然后才是数据库机制问题。数据库只是在帮你实现一致性,但“一致性到底划到哪里”必须由业务来决定。

MyBatis 和 JPA 的取舍,本质上在取舍什么?

这两个框架很容易被讨论成“谁更先进”。这种问法本身就不够成熟。更实用的判断通常是:

  • 如果查询复杂、报表多、SQL 控制要求高,MyBatis 往往更合适;
  • 如果模型稳定、CRUD 居多、团队偏模型驱动,JPA 往往更顺手。

这说明你真正取舍的,不是工具潮流,而是:

  • 你需要多少 SQL 控制力;
  • 你愿意承受多少抽象层;
  • 团队更擅长围绕数据库思考,还是围绕实体模型思考;
  • 性能排查时,希望更贴近 SQL,还是接受更高层封装。

没有哪一种永远“更高级”,核心永远是当前项目更需要哪种边界。

连接池为什么一定要尽早纳入视野?

很多新手一开始对连接池感受不深,因为本地开发里数据量和并发都不大。但一旦进入真实项目,连接池几乎立刻会成为稳定性关键点。因为数据库连接不是无限资源:

  • 建立连接有成本;
  • 空闲连接也要管理;
  • 并发请求一上来,连接耗尽会直接拖垮服务;
  • 慢查询和事务过大也会把连接长时间占住。

所以连接池不是“后面优化时再说”的点,而是数据访问链路里的基础设施之一。

放到项目里,怎样组织会更稳?

真实项目里,更稳的做法通常是:

  • 先把事务边界想清楚,再决定数据访问层怎样拆;
  • 复杂查询优先保证 SQL 可控;
  • 常规 CRUD 再借助 ORM 或映射框架提效;
  • 数据访问细节集中在仓储层或 Mapper 层,不要散落到 Controller;
  • 连接池、慢查询观测、索引意识尽早接入。

也就是说,数据层真正稳定的关键,不是某个框架选对了,而是“查询、事务、资源治理、分层边界”这几件事有没有一起被看见。

最容易踩的坑

最常见的问题包括:

  • 把事务开得过大,导致锁等待和性能问题;
  • 误以为 ORM 能自动解决所有查询设计;
  • 连接池参数默认到底,从不观察真实负载;
  • 仓储层边界不清,控制器和服务层直接写数据库逻辑;
  • 还没把基础数据访问理顺,就过早讨论复杂架构。

总结

Java 数据访问真正要解决的,是一致性、可维护性和性能边界。JDBC、事务、连接池、MyBatis、JPA 这些能力并不是互相竞争,而是在不同层级共同构成数据访问主线。只要你先把“事务怎么划、SQL 控制力怎么选、资源怎样治理”这几件事看清楚,后面的数据库协作就不再只是“能查能写”那么简单。