掌握MyBatis Java API:高效操作数据库
以下内容是 MyBatis 官方文档中关于 Java API 的详细说明,主要讲解了如何使用 MyBatis 的核心类和接口来操作数据库。你在最后问:“怎么理解”,我将为你系统地梳理并通俗易懂地解释这一整段内容的核心思想、关键概念以及实际开发中的意义。
🌟 总体理解:MyBatis Java API 是什么?
简单来说,MyBatis 的 Java API 就是你在代码里用来和数据库交互的“工具包”。
它封装了 JDBC 所需的繁琐步骤(如连接、预编译 SQL、结果集处理等),让你可以用更简洁、类型安全的方式执行 SQL 操作,同时保持对 SQL 的完全控制。
✅ 核心目标:简化 JDBC 编程,避免重复代码,提高可维护性
🔍 分模块解析
1. 目录结构建议(Directory Structure)
虽然 MyBatis 不强制目录结构,但推荐一个清晰的组织方式:
/src/org/myapp//data ← 放 MyBatis 配置文件、Mapper 接口、XML 映射文件mybatis-config.xml ← 主配置文件BlogMapper.java ← Mapper 接口BlogMapper.xml ← SQL 映射文件
📌 为什么重要?
- 统一结构方便团队协作。
- XML 文件与对应的 Mapper 接口放在一起,便于查找和管理。
2. SqlSessionFactoryBuilder → 构建工厂的“建造者”
作用:从 mybatis-config.xml
或 Java 配置对象创建出 SqlSessionFactory
。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
🔧 常用方法:
SqlSessionFactory build(InputStream input);
SqlSessionFactory build(Configuration config); // 手动编码配置
💡 提示:
Resources
是 MyBatis 提供的工具类,用于加载 classpath 下的资源。- 如果用了 Spring,这一步通常由框架自动完成。
3. SqlSessionFactory → 生产 SqlSession 的“工厂”
它是线程安全的单例,整个应用只需要一个实例。
SqlSessionFactory factory = ...; // 创建一次即可
提供多个 openSession()
方法来生成 SqlSession
,常见组合:
参数 | 含义 |
---|---|
openSession() | 默认:开启事务(非自动提交) |
openSession(true) | 自动提交模式 |
openSession(connection) | 使用自定义连接 |
openSession(ExecutorType.BATCH) | 批量执行更新 |
🧠 关键点:
ExecutorType.SIMPLE
: 每次都新建 PreparedStatementExecutorType.REUSE
: 复用 PreparedStatementExecutorType.BATCH
: 批量插入/更新,性能高
4. SqlSession → 和数据库交互的“会话”
这是最核心的对象!你可以用它做三件事:
✅ (1) 执行 SQL(原始方式)
Author author = session.selectOne("selectAuthor", 5);
List<Author> authors = session.selectList("selectAuthors");
int rows = session.insert("insertAuthor", author);
session.update("updateAuthor", author);
session.delete("deleteAuthor", 5);
⚠️ 缺点:
- 字符串硬编码
"selectAuthor"
,容易拼错 - 不是类型安全(返回 Object 类型需要强转)
- IDE 无法提示错误
所以——👉 更推荐下面的 Mapper 方式
✅ (2) 使用 Mapper 接口(推荐方式)
创建一个接口,MyBatis 自动帮你实现!
public interface AuthorMapper {Author selectAuthor(int id);List<Author> selectAuthors();@MapKey("id") Map<Integer, Author> selectAuthorsMap();int insertAuthor(Author author);
}
然后获取代理对象调用:
try (SqlSession session = sqlSessionFactory.openSession()) {AuthorMapper mapper = session.getMapper(AuthorMapper.class);Author author = mapper.selectAuthor(101);
}
🎯 优势:
- 类型安全 ✅
- 方法名即 SQL ID(无需字符串)
- 可被单元测试、IDE 检查 ✅
- 写法简洁 ✅
✅ (3) 控制事务
session.commit(); // 提交事务
session.rollback(); // 回滚
默认情况下:
openSession()
不自动提交 → 必须手动 commit- 如果没 commit 而 close,MyBatis 会自动 rollback
✅ (4) 结果处理高级功能
a) RowBounds:分页(逻辑分页)
RowBounds rowBounds = new RowBounds(100, 25); // 跳过100条,取25条
List<Author> list = session.selectList("selectAuthors", null, rowBounds);
⚠️ 注意:这是内存中分页(先查所有再截取),不是物理分页。生产环境建议配合插件(如 PageHelper)或手写 LIMIT。
b) ResultHandler:逐行处理大数据
适合处理百万级数据,避免 OOM。
session.select("selectAuthors", null, new ResultHandler<Author>() {public void handleResult(ResultContext<? extends Author> context) {Author author = context.getResultObject();// 处理每一行数据}
});
💡 内部原理类似迭代器,边读边处理。
c) Cursor:懒加载游标(MyBatis 3.4+)
try (Cursor<Author> cursor = session.selectCursor("selectAuthors")) {for (Author author : cursor) {// 逐条处理}
}
比 List
更省内存。
5. Mapper 注解(Annotation)→ 无 XML 写法
MyBatis 支持用注解代替 XML 写 SQL。
@Select("SELECT * FROM author WHERE id = #{id}")
Author selectAuthor(int id);@Insert("INSERT INTO author(name) VALUES(#{name})")
@SelectKey(statement="CALL IDENTITY()", keyProperty="id", before=false, resultType=int.class)
int insertAuthor(Author author);
📌 常见注解:
注解 | 对应 XML | 用途 |
---|---|---|
@Select , @Insert , @Update , @Delete | <select> , <insert> 等 | 写 SQL |
@SelectKey | <selectKey> | 获取主键(如自增) |
@Results , @Result | <resultMap> | 字段映射 |
@One / @Many | <association> , <collection> | 一对一、一对多关联查询 |
@Options | <insert useGeneratedKeys="true"...> | 设置选项 |
@Param | —— | 给参数命名 |
@MapKey | —— | 把 List 转成 Map,指定 key 属性 |
❗ 局限性:
- 复杂 SQL(多表 join、动态 SQL)很难用注解表达
- 动态 SQL(if、foreach)必须用
@SelectProvider
等提供器
例如动态 SQL:
@SelectProvider(type = SqlProvider.class, method = "selectBlogSQL")
List<Blog> selectBlogs(String title, String content);
public class SqlProvider {public String selectBlogSQL(String title, String content) {return new SQL() {{SELECT("*");FROM("blog");if (title != null) WHERE("title like #{title}");if (content != null) WHERE("content like #{content}");}}.toString();}
}
这种方式比纯字符串拼接更安全、易读。
6. 缓存机制
MyBatis 有两级缓存:
一级缓存(Local Cache)✅ 默认开启
- 作用范围:同一个
SqlSession
- 同一个 SQL + 参数 第二次查询直接从缓存取
- 更新、commit、rollback、close 都会清空缓存
⚠️ 注意:
- 返回的是引用!修改结果会影响缓存 → 建议不要修改返回对象
- 可设置
localCacheScope=STATEMENT
关闭会话级缓存
二级缓存(需要手动配置)📦
- 跨 SqlSession 共享
- 需要在 Mapper XML 中加
<cache/>
或用@CacheNamespace
🧩 最佳实践总结
实践 | 建议 |
---|---|
✅ 使用 Mapper 接口 | 而不是直接调用 sqlSession.xxx() |
✅ 优先使用 XML 映射 | 复杂 SQL 更清晰 |
✅ 简单 SQL 可用注解 | 减少 XML 文件数量 |
✅ 正确关闭 SqlSession | 用 try-with-resources |
✅ 分页用物理分页插件 | 如 PageHelper,避免 RowBounds 内存溢出 |
✅ 不要修改查询返回的对象 | 防止污染一级缓存 |
✅ 合理使用二级缓存 | 注意并发和脏读问题 |
📦 示例完整流程(不依赖 Spring)
// 1. 加载配置文件,创建 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream input = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(input);// 2. 获取 SqlSession
try (SqlSession session = factory.openSession()) {// 3. 获取 MapperAuthorMapper mapper = session.getMapper(AuthorMapper.class);// 4. 执行操作Author author = mapper.selectAuthor(1);System.out.println(author.getName());// 5. 提交事务(如果是 insert/update/delete)session.commit();
} // 自动关闭 session
✅ 总结一句话:
MyBatis Java API 的本质是:通过 SqlSessionFactory 创建 SqlSession,再通过 SqlSession 获取 Mapper 接口的代理对象,从而以面向接口的方式安全、简洁地执行 SQL 操作。
这套 API 极大地简化了 JDBC 开发,既保留了 SQL 的灵活性,又提供了 ORM 的便利性。
如果你想进一步了解:
- 如何整合 Spring?
- 如何实现分页?
- 如何处理一对多映射?
- 如何调试 SQL 输出?
欢迎继续提问 😊