MyBatis 的前身是 Apache ibatis,其内部包含了很多易于操作的 API。

SqlSession

SqlSession 是 MyBatis 的核心接口,通过这个接口,我们可以执行命令、获取映射器以及管理事务。其核心方法如下:

语句执行方法

一般方法

这些方法用于执行在映射配置文件中定义的 SELECTINSERTUPDATEDELETE 语句。它们都相当直观,每个方法都接受语句的 ID 和参数对象作为输入。参数对象可以是原始类型(或包装类)、JavaBean、POJO 或 Map。

  <T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)
  

其中:

  • selectOneselectList 的区别仅在于 selectOne 必须严格返回一个对象或者 null(没有结果)。如果返回超过一个对象,将抛出异常。

  • insertupdatedelete 方法返回的值表示语句影响的行数。

  • selectMap 是一个特殊情况,它被设计用来根据结果对象中的某个属性将结果列表转换成 Map。

  • 并非所有的语句都需要参数,因此这些方法还有它们不需要参数对象的重载版本:

      <T> T selectOne(String statement)
    <E> List<E> selectList(String statement)
    <T> Cursor<T> selectCursor(String statement)
    <K,V> Map<K,V> selectMap(String statement, String mapKey)
    int insert(String statement)
    int update(String statement)
    int delete(String statement)
      
  • 带游标的方法 selectCursor 的作用与 selectList 相同,不过它支持通过 Iterator 来延迟获取数据,使用实例如下:

      try (Cursor<MyEntity> entities = session.selectCursor(statement, param)) {
        for (MyEntity entity : entities) {
            // process one entity
        }
    }
      

带 RowBounds 的高级方法

MyBatis 还提供了一套带有 RowBounds 的高级 SELECT 方法。这些方法支持限定要返回的行范围,或提供自定义的结果处理逻辑,通常用于对大数据集的分页查询和结果处理:

  <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)
  

其中:

  • RowBounds 只能通过构造函数设置偏移量和限制数量,示例如下:

      int offset = 100;
    int limit = 25;
    RowBounds rowBounds = new RowBounds(offset, limit);
      
  • ResultHandler 允许自定义数据处理过程,例如将数据存储 List、Map、Set,甚至直接丢弃所有结果仅返回计算总和。其接口如下:

      package org.apache.ibatis.session;
    public interface ResultHandler<T> {
        void handleResult(ResultContext<? extends T> context);
    }
      
    • 我们只需实现这个接口方法,就能自定义数据处理过程。
    • ResultContext 参数提供了对结果对象本身的访问,以及创建的结果对象数量的计数。

批量更新语句刷新方法

ExecutorTypeExecutorType.BATCH 时,可以通过该方法执行存储在 JDBC 驱动程序类中的批量更新语句:

  List<BatchResult> flushStatements()
  

事务控制方法

MyBatis 提供了四种控制事务范围的方法:

  void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
  

当开启了自动提交或使用了外部事务管理器时,以上方法将失效。

默认情况下,MyBatis 仅当检测到通过 INSERTUPDATEDELETE 或带有 affectData 参数的 SELECT 方法对数据库进行更改时,才会执行提交操作。如果在未调用这些方法的情况下进行了更改,可通过将 true 传递给 commit()rollback() 方法来确保提交。

通常情况下,我们不需要显式调用 rollback() 方法,因为未调用 commit 时,MyBatis 将自动执行回滚操作。

清空缓存 clearCache

MyBatis 使用两级缓存:本地缓存和二级缓存。

每次创建新的会话时,MyBatis 都会创建一个本地缓存并将其附加到会话上。会话内执行的任何查询都将存储在本地缓存中,因此对相同输入参数执行相同查询的后续操作不会再访问数据库。本地缓存会在更新、提交、回滚和关闭时清空。

默认情况下,本地缓存数据在整个会话期间都可用。此缓存用于解决循环引用和加速重复嵌套查询,因此无法完全禁用,但我们可以通过设置 localCacheScope=STATEMENT,仅在语句执行期间使用本地缓存。

如果要手动清空缓存,可以调用以下方法:

  void clearCache()
  

关闭 SqlSession

  void close()
  

该方法用于关闭 SqlSession。每个会话在使用完成后,都应当被关闭。

获取 Mapper

当今,代理开发模式已经成为企业开发的主流。我们只需编写 Mapper 接口,MyBatis 框架就会为我们动态生成实现类的对象。

  <T> T getMapper(Class<T> type)
  

SqlSessionFactory

介绍完 SqlSession 后,我们接下来介绍如何创建 SqlSession。MyBatis 通过 SqlSessionFactory 创建 SqlSession 实例,这是典型的工厂模式应用。

SqlSessionFactory 内部提供了多种创建 SqlSession 实例的方法,一般情况下,在选择这些方法时需要考虑以下因素:

  • 是否启用事务;
  • 连接从数据源中获取,还是自己手动获取;
  • 是否使用 PreparedStatement、是否进行批量更新/删除。
  SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();
  

其中:

  • TransactionIsolationLevel:该枚举用于设定事务隔离级别。其支持 JDBC 提供的五个隔离级别:NONEREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE
  • ExecutorType 内定义了三个枚举值:
    • ExecutorType.SIMPLE:此类型的执行器不执行特殊操作。它为每次执行语句创建一个新的 PreparedStatement
    • ExecutorType.REUSE:此类型的执行器将重用 PreparedStatement
    • ExecutorType.BATCH:此执行器将所有更新语句批处理。

SqlSessionFactoryBuilder

MyBatis 的 SqlSessionFactory 是通过构造者模式创建的。SqlSessionFactoryBuilder 提供了五个 build() 方法,每个方法允许从不同的源构建一个 SqlSessionFactory

  SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)
  

以下是一个使用示例:

  String resource = "me/iling/builder/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);