核心接口
本文将详细介绍 MyBatis 的核心 API,包括 SqlSessionFactoryBuilder、SqlSessionFactory 以及 SqlSession 的核心方法。
MyBatis 的前身是 Apache ibatis,其内部包含了很多易于操作的 API。
SqlSession
SqlSession
是 MyBatis 的核心接口,通过这个接口,我们可以执行命令、获取映射器以及管理事务。其核心方法如下:
语句执行方法
一般方法
这些方法用于执行在映射配置文件中定义的 SELECT
、INSERT
、UPDATE
和 DELETE
语句。它们都相当直观,每个方法都接受语句的 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)
其中:
selectOne
和selectList
的区别仅在于 selectOne 必须严格返回一个对象或者 null(没有结果)。如果返回超过一个对象,将抛出异常。insert
、update
和delete
方法返回的值表示语句影响的行数。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
参数提供了对结果对象本身的访问,以及创建的结果对象数量的计数。
批量更新语句刷新方法
当 ExecutorType
是 ExecutorType.BATCH
时,可以通过该方法执行存储在 JDBC 驱动程序类中的批量更新语句:
List<BatchResult> flushStatements()
事务控制方法
MyBatis 提供了四种控制事务范围的方法:
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
当开启了自动提交或使用了外部事务管理器时,以上方法将失效。
默认情况下,MyBatis 仅当检测到通过 INSERT
、UPDATE
、DELETE
或带有 affectData
参数的 SELECT
方法对数据库进行更改时,才会执行提交操作。如果在未调用这些方法的情况下进行了更改,可通过将 true 传递给 commit()
和 rollback()
方法来确保提交。
通常情况下,我们不需要显式调用 rollback()
方法,因为未调用 commit 时,MyBatis 将自动执行回滚操作。
清空缓存 clearCache
MyBatis 使用两级缓存:本地缓存和二级缓存。
每次创建新的会话时,MyBatis 都会创建一个本地缓存并将其附加到会话上。会话内执行的任何查询都将存储在本地缓存中,因此对相同输入参数执行相同查询的后续操作不会再访问数据库。本地缓存会在更新、提交、回滚和关闭时清空。
默认情况下,本地缓存数据在整个会话期间都可用。此缓存用于解决循环引用和加速重复嵌套查询,因此无法完全禁用,但我们可以通过设置 localCacheScope=STATEMENT
,仅在语句执行期间使用本地缓存。
localCacheScope
设置为 SESSION
时,MyBatis 返回的是本地缓存中存储的同一对象的引用。对返回的对象(例如列表)进行任何修改都会影响本地缓存的内容,从而影响会话生命周期内从缓存中返回的值。因此,最佳实践是不要修改 MyBatis 返回的对象。如果要手动清空缓存,可以调用以下方法:
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 提供的五个隔离级别:NONE
、READ_UNCOMMITTED
、READ_COMMITTED
、REPEATABLE_READ
、SERIALIZABLE
。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);