MyBatis 是 Java 后端常用的持久层框架。它不像 JPA 那样尽量屏蔽 SQL,而是把 SQL 显式交给开发者管理,再提供参数绑定、结果映射、动态 SQL、Mapper 接口等能力。对于供应链系统来说,订单、库存、仓储、采购、结算等模块经常需要精细控制 SQL,MyBatis 很适合这类场景。
整体流程
MyBatis 解决什么问题
直接使用 JDBC 时,开发者通常要重复处理连接、预编译 SQL、参数绑定、结果集转换和资源关闭。MyBatis 把这些模板代码收敛起来,让开发者把注意力放在 SQL 和对象映射上。
核心能力包括:
- Mapper 接口:用 Java 方法表达一次数据库操作。
- XML 或注解 SQL:显式管理 SQL,便于优化。
- 参数绑定:避免手工拼接 SQL,降低 SQL 注入风险。
- 结果映射:把查询结果转换成 Java 对象。
- 动态 SQL:根据条件生成不同查询。
供应链例子:库存查询
先定义库存表:
1 | CREATE TABLE scm_inventory ( |
Java 对象:
1 | public class InventoryRecord { |
Mapper 接口:
1 | public interface InventoryMapper { |
XML 映射:
1 | <mapper namespace="com.example.inventory.InventoryMapper"> |
这里的 #{} 是预编译参数绑定,不是字符串拼接。它会交给 JDBC PreparedStatement 处理,能避免大部分 SQL 注入风险。
动态 SQL
供应链系统经常有多条件查询,例如按仓库、SKU、是否低库存过滤:
1 | public class InventoryQuery { |
动态 SQL:
1 | <select id="search" resultMap="InventoryRecordMap"> |
<where> 会自动处理多余的 AND,比在 Java 里拼接字符串更清晰。
常见误区
第一,#{} 和 ${} 不能混用。#{} 是参数绑定,${} 是文本替换。只有表名、排序字段这类无法预编译的位置才可能使用 ${},并且必须做白名单校验。
1 | private static final Set<String> ALLOWED_SORT_FIELDS = |
第二,Mapper 方法不要返回过大的集合。库存流水、订单流水、报表明细必须分页查询,否则容易造成堆内存压力。
第三,SQL 要命中索引。比如 warehouse_id + sku_id 是库存查询的高频条件,就应该建立联合唯一索引。
小结
MyBatis 的价值在于让 SQL 可控,同时减少 JDBC 模板代码。供应链系统的数据一致性和查询性能很依赖 SQL 质量,因此掌握 Mapper、结果映射、动态 SQL、参数绑定和索引配合,是使用 MyBatis 的基础能力。