MyBatis 是一款优秀的持久层(ORM)框架,它支持自定义 SQL、存储过程以及高级映射

MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

MyBatis 可以通过简单的 XML注解来配置和映射 原始类型接口Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

原始类型接口POJO数据库中的记录的映射

依赖

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>

构建 SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。

SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。

SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个 预先配置的 Configuration 实例 来构建出 SqlSessionFactory 实例。

从XML配置构建

  1. 声明配置文件路径
  2. 用Resources工具类读取配置文件得到输入流
  3. 使用SqlSessionFactoryBuilder 构建输入流得到SqlSessionFactory
1
2
3
String path = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(path);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

从Java代码创建(无配置文件)

要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XML 映射文件进行映射。

  1. 获取数据源
  2. 创建事务工厂
  3. 创建Environment对象,传入环境名,事务工厂对象,数据源
  4. 创建Configuration对象,传入环境对象
  5. 添加 映射器
  6. 使用 SqlSessionFactoryBuilder 构建输入流得到SqlSessionFactory
1
2
3
4
5
6
7
8
9
10
11
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();

TransactionFactory transactionFactory = new JdbcTransactionFactory();

Environment environment = new Environment("development", transactionFactory, dataSource);

Configuration configuration = new Configuration(environment);

configuration.addMapper(BlogMapper.class);

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

SqlSession

SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。

我们可以从中获得 SqlSession 的实例。

传入映射器方法路径方式

1
2
3
try (SqlSession session = sqlSessionFactory.openSession()) {
Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}

传入映射器class方式(推荐)

1
2
3
4
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
}

它不依赖于字符串字面值,会更安全一点, IDE 有代码补全功能,那么代码补全可以帮你快速选择到映射好的 SQL 语句

作用域 和 生命周期

1. SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。

因此 SqlSessionFactoryBuilder 实例的最佳作用域是 方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

2. SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。

使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。

因此 SqlSessionFactory 的最佳作用域是 应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

3. SqlSession

每个线程都应该有它自己的 SqlSession 实例。

SqlSession 的实例不是线程安全的,因此是不能被共享的,所以SqlSession 的最佳的作用域是 请求 或 方法作用域

绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。

也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。

这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:

1
2
3
try (SqlSession session = sqlSessionFactory.openSession()) {
// 你的应用逻辑代码
}

4. Mapper

映射器是一些绑定映射语句的接口。映射器接口的实例是从 SqlSession 中获得的。

虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的 SqlSession 相同。

映射器实例的最合适的作用域 是方法作用域

也就是说,映射器实例并不需要被显式地关闭,映射器实例应该在调用它们的方法中被获取,使用完毕之后即可丢弃。