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 控制力怎么选、资源怎样治理”这几件事看清楚,后面的数据库协作就不再只是“能查能写”那么简单。