1. 简介

MyBatis 是一个开源持久化框架,能简化 Java 应用中的数据库访问实现。它支持自定义 SQL、存储过程以及多种映射关系。

简单说,它是 JDBC 和 Hibernate 的替代方案。

2. Maven 依赖

要在项目中使用 MyBatis,需在 pom.xml 中添加依赖:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>

最新版本可在 这里 查找。

3. 核心 API

3.1. SQLSessionFactory

SQLSessionFactory 是每个 MyBatis 应用的核心类。通过 SQLSessionFactoryBuilderbuild() 方法加载配置 XML 文件实例化:

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SQLSessionFactory sqlSessionFactory
  = new SqlSessionFactoryBuilder().build(inputStream);

Java 配置文件包含数据源定义、事务管理器详情和实体映射关系列表,共同构建 SQLSessionFactory 实例:

public static SqlSessionFactory buildqlSessionFactory() {
    DataSource dataSource 
      = new PooledDataSource(DRIVER, URL, USERNAME, PASSWORD);

    Environment environment 
      = new Environment("Development", new JdbcTransactionFactory(), dataSource);
        
    Configuration configuration = new Configuration(environment);
    configuration.addMapper(PersonMapper.class);
    // ...

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    return builder.build(configuration);
}

3.2. SQLSession

SQLSession 包含执行数据库操作、获取映射器和管理事务的方法。通过 SQLSessionFactory 实例化,非线程安全

操作完成后必须关闭会话。由于 SqlSession 实现了 AutoCloseable 接口,推荐使用 try-with-resources:

try(SqlSession session = sqlSessionFactory.openSession()) {
    // 执行操作
}

4. 映射器

映射器是 Java 接口,将方法映射到对应的 SQL 语句。MyBatis 提供注解定义数据库操作:

public interface PersonMapper {

    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);

    // ...

    @Select(
      "Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType = List.class,
        column = "personId", many=@Many(select = "getAddresses"))
    })
    public Person getPersonById(Integer personId);

    // ...
}

5. 核心注解

以下是 MyBatis 的主要注解及用法:

基础操作注解

  • @Insert, @Select, @Update, @Delete:定义增删改查语句
    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);
    
    @Update("Update Person set name= #{name} where personId=#{personId}")
    public void updatePerson(Person person);
    
    @Delete("Delete from Person where personId=#{personId}")
    public void deletePersonById(Integer personId);
    
    @Select("SELECT person.personId, person.name FROM person 
      WHERE person.personId = #{personId}")
    Person getPerson(Integer personId);
    

结果映射注解

  • @Results:定义数据库列到 Java 属性的映射规则
    @Select("Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId")
        // ...   
    })
    public Person getPersonById(Integer personId);
    
  • @Result:单个结果映射,包含列名、属性名、Java 类型等
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType =List.class) 
        // ... 
    })
    public Person getPersonById(Integer personId);
    

关联映射注解

  • @Many:一对多关系映射
    @Results(value ={
      @Result(property = "addresses", javaType = List.class, 
        column = "personId",
        many=@Many(select = "getAddresses"))
    })
    
    对应的查询方法:
    @Select("select addressId, streetAddress, personId from address 
      where personId=#{personId}")
    public Address getAddresses(Integer personId);
    
  • @One:一对一关系映射(用法类似 @Many

高级功能注解

  • @MapKey:将查询结果转为 Map
    @Select("select * from Person")
    @MapKey("personId")
    Map<Integer, Person> getAllPerson();
    
  • @Options:配置语句选项(如主键生成、缓存控制)
    @Insert("Insert into address (streetAddress, personId) 
      values(#{streetAddress}, #{personId})")
    @Options(useGeneratedKeys = false, flushCache=true)
    public Integer saveAddress(Address address);
    

6. 动态 SQL

动态 SQL 是 MyBatis 的杀手级功能,能精准构建复杂 SQL 语句。相比传统 JDBC 拼接 SQL 的方式(容易踩坑),它更安全高效。

使用 @SelectProvider 指定 SQL 构建类和方法:

@SelectProvider(type=MyBatisUtil.class, method="getPersonByName")
public Person getPersonByName(String name);

SQL 构建类示例:

public class MyBatisUtil {
 
    // ...
 
    public String getPersonByName(String name){
        return new SQL() {{
            SELECT("*");
            FROM("person");
            WHERE("name like #{name} || '%'");
        }}.toString();
    }
}

动态 SQL 将 SQL 关键字(SELECT/WHERE 等)封装为类,可灵活构建条件语句。

7. 存储过程支持

通过 @Select 注解调用存储过程,需显式使用 CALL 并指定参数模式:

@Select(value= "{CALL getPersonByProc(#{personId,
  mode=IN, jdbcType=INTEGER})}")
@Options(statementType = StatementType.CALLABLE)
public Person getPersonByProc(Integer personId);

8. iBATIS vs MyBatis

MyBatis 前身是 iBATIS,两者核心差异:

特性 iBATIS MyBatis
包名 com.ibatis org.mybatis
注解支持 ❌ 仅 XML 配置 ✅ 支持注解 + XML
动态 SQL 仅 XML 标签(灵活性低) ✅ Java 构建器(如 SQLProvider
映射器接口 需显式 DAO 类(代码冗余) ✅ 直接接口映射(减少样板代码)
配置方式 强依赖 XML ✅ XML + Java 配置双模式
社区维护 ❌ 已停止更新 ✅ 持续迭代
性能优化 基础实现(性能一般) ✅ 查询优化 + 内存优化
缓存机制 基础缓存(功能有限) ✅ 一级/二级缓存 + 可配置
存储过程支持 需 XML 配置 ✅ 注解直接支持

⚠️ 关键升级点:MyBatis 通过注解简化开发,增强动态 SQL 能力,并优化与现代框架(如 Spring)的集成。

9. 总结

本文梳理了 MyBatis 的核心能力:

  • 通过映射器和注解消除 JDBC 样板代码
  • 动态 SQL 灵活构建复杂查询
  • 完善的关联映射和存储过程支持
  • 相比 iBATIS 的显著性能与易用性提升

MyBatis 在 SQL 灵活性和开发效率间取得了绝佳平衡,是 Java 持久层方案的务实选择。


原始标题:Quick Guide to MyBatis | Baeldung