以下内容是 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。
            
            
              java
              
              
            
          
          InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        🔧 常用方法:
            
            
              java
              
              
            
          
          SqlSessionFactory build(InputStream input);
SqlSessionFactory build(Configuration config); // 手动编码配置
        💡 提示:
Resources是 MyBatis 提供的工具类,用于加载 classpath 下的资源。- 如果用了 Spring,这一步通常由框架自动完成。
 
3. SqlSessionFactory → 生产 SqlSession 的"工厂"
它是线程安全的单例,整个应用只需要一个实例。
            
            
              java
              
              
            
          
          SqlSessionFactory factory = ...; // 创建一次即可
        提供多个 openSession() 方法来生成 SqlSession,常见组合:
| 参数 | 含义 | 
|---|---|
openSession() | 
默认:开启事务(非自动提交) | 
openSession(true) | 
自动提交模式 | 
openSession(connection) | 
使用自定义连接 | 
openSession(ExecutorType.BATCH) | 
批量执行更新 | 
🧠 关键点:
ExecutorType.SIMPLE: 每次都新建 PreparedStatementExecutorType.REUSE: 复用 PreparedStatementExecutorType.BATCH: 批量插入/更新,性能高
4. SqlSession → 和数据库交互的"会话"
这是最核心的对象!你可以用它做三件事:
✅ (1) 执行 SQL(原始方式)
            
            
              java
              
              
            
          
          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 自动帮你实现!
            
            
              java
              
              
            
          
          public interface AuthorMapper {
    Author selectAuthor(int id);
    List<Author> selectAuthors();
    @MapKey("id") Map<Integer, Author> selectAuthorsMap();
    int insertAuthor(Author author);
}
        然后获取代理对象调用:
            
            
              java
              
              
            
          
          try (SqlSession session = sqlSessionFactory.openSession()) {
    AuthorMapper mapper = session.getMapper(AuthorMapper.class);
    Author author = mapper.selectAuthor(101);
}
        🎯 优势:
- 类型安全 ✅
 - 方法名即 SQL ID(无需字符串)
 - 可被单元测试、IDE 检查 ✅
 - 写法简洁 ✅
 
✅ (3) 控制事务
            
            
              java
              
              
            
          
          session.commit();     // 提交事务
session.rollback();   // 回滚
        默认情况下:
openSession()不自动提交 → 必须手动 commit- 如果没 commit 而 close,MyBatis 会自动 rollback
 
✅ (4) 结果处理高级功能
a) RowBounds:分页(逻辑分页)
            
            
              java
              
              
            
          
          RowBounds rowBounds = new RowBounds(100, 25); // 跳过100条,取25条
List<Author> list = session.selectList("selectAuthors", null, rowBounds);
        ⚠️ 注意:这是内存中分页(先查所有再截取),不是物理分页。生产环境建议配合插件(如 PageHelper)或手写 LIMIT。
b) ResultHandler:逐行处理大数据
适合处理百万级数据,避免 OOM。
            
            
              java
              
              
            
          
          session.select("selectAuthors", null, new ResultHandler<Author>() {
    public void handleResult(ResultContext<? extends Author> context) {
        Author author = context.getResultObject();
        // 处理每一行数据
    }
});
        💡 内部原理类似迭代器,边读边处理。
c) Cursor:懒加载游标(MyBatis 3.4+)
            
            
              java
              
              
            
          
          try (Cursor<Author> cursor = session.selectCursor("selectAuthors")) {
    for (Author author : cursor) {
        // 逐条处理
    }
}
        比 List 更省内存。
5. Mapper 注解(Annotation)→ 无 XML 写法
MyBatis 支持用注解代替 XML 写 SQL。
            
            
              java
              
              
            
          
          @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:
            
            
              java
              
              
            
          
          @SelectProvider(type = SqlProvider.class, method = "selectBlogSQL")
List<Blog> selectBlogs(String title, String content);
        
            
            
              java
              
              
            
          
          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)
            
            
              java
              
              
            
          
          // 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. 获取 Mapper
    AuthorMapper 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 输出?
 
欢迎继续提问 😊