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 应用的核心类。通过 SQLSessionFactoryBuilder
的 build()
方法加载配置 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 持久层方案的务实选择。