SqlSessions

使用 MyBatis 的主要 Java 接口就是 SqlSession。我们可以通过这个接口来执行命令,获取映射器和管理事务。SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的所有方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或手动配置 Java 代码来创建 SqlSessionFactory

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 有五个 build() 方法,每一种都从不同的资源中创建一个 SqlSession 实例

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)

第一种方法是最常用的,它mybatis.xml即全局配置文件的 Reader 实例。可选的参数是 environment 和 properties。environment 决定加载哪种环境,包括数据源和事务管理器。比如:

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
        ...
    <dataSource type="POOLED">
        ...
  </environment>
  <environment id="production">
    <transactionManager type="MANAGED">
        ...
    <dataSource type="JNDI">
        ...
  </environment>
</environments>

如果调用了参数有 environment 的 build 方法,那么 MyBatis 将会使用 configuration 对象来配置这个 environment。如果调用了不带 environment 参数的 build 方法,那么就使用默认的 environment(在上面的示例中指定为 default=“development” 的代码)

String resource = "org/mybatis/builder/mybatis-config.xml";
//读取全局配置文件
//Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类正如其名,会帮助你从类路径下、文件系统或一个 web URL 中加载资源文件
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

最后一个 build 方法的参数为 Configuration 实例。configuration 类包含可能需要了解 SqlSessionFactory 实例的所有内容这里有一个简单的示例,指导如何手动配置 configuration 实例,然后将它传递给 build() 方法来创建 SqlSessionFactory:

//数据源
DataSource dataSource = BaseDataTest.createBlogDataSource();
//事务管理器
TransactionFactory transactionFactory = new JdbcTransactionFactory();

//环境内需要配置事务管理器和数据源
Environment environment = new Environment("development", transactionFactory, dataSource);
//传入环境实例构造configuration实例
Configuration configuration = new Configuration(environment);
configuration.setLazyLoadingEnabled(true);
configuration.setEnhancementEnabled(true);
//设置别名
configuration.getTypeAliasRegistry().registerAlias(Blog.class);
configuration.getTypeAliasRegistry().registerAlias(Post.class);
configuration.getTypeAliasRegistry().registerAlias(Author.class);
//获取映射器
configuration.addMapper(BoundBlogMapper.class);
configuration.addMapper(BoundAuthorMapper.class);

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);
SqlSessionFactory

SqlSessionFactory 有六个方法创建 SqlSession 实例。选择方法时需要注意:

  • 事务管理:是否需要在session中使用事务自动提交功能
  • 连接:是否需要依赖MyBatis获得来自数据源的配置,还是使用自己提供的配置
  • 执行语句:是否需要MyBatis复用预处理语句或批量更新语句
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();

默认的openSession()语句没有参数,会创建有如下特性的SqlSession:

  • 会开启一个事务,不自动提交,需要手动提交
  • 将从由当前环境配置的数据源实例中获取Connection对象
  • 事务隔离级别将会使用驱动或数据源的默认配置
  • 预处理语句不会被复用,也不会批量处理更新
  • autoCommit 可选参数传递 true 值即可开启自动提交功能
  • 若要使用自己的 Connection 实例,传递一个 Connection 实例给 connection 参数即可
  • myBatis 为事务隔离级别调用使用了一个 Java 枚举包装器,称为 TransactionIsolationLevel,若不使用它,将使用 JDBC 所支持五个隔离级(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE),并按它们预期的方式来工作
  • ExecutorType,这个枚举类型定义了三个值:
    – ExecutorType.SIMPLE:这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句
    – ExecutorType.REUSE:这个执行器类型会复用预处理语句
    – ExecutorType.BATCH:这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行,必要时请把它 们区分开来以保证行为的易读性

SqlSession

执行语句方法

这些方法被用来执行定义在 SQL 映射的 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 语句,每一句都使用语句的 ID 属性和参数对象,参数可以是原生类型(自动装箱或包装类)、JavaBean、POJO 或 Map

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(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 值。如果返回值多于一个,那么就会抛出异常。如果你不知道返回对象的数量,请使用 selectList。如果需要查看返回对象是否存在,可行的方案是返回一个值即可(0 或 1)。selectMap 稍微特殊一点,因为它会将返回的对象的其中一个属性作为 key 值,将对象作为 value 值,从而将多结果集转为 Map 类型值

因为并不是所有语句都需要参数,所以这些方法都重载成不需要参数的形式

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

最后,还有 select 方法的三个高级版本,它们允许你限制返回行数的范围,或者提供自定义结果控制逻辑,这通常在数据集合庞大的情形下使用。

<E> List<E> selectList (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 参数会告诉 MyBatis 略过指定数量的记录,还有限制返回结果的数量。RowBounds 类有一个构造方法来接收 offset 和 limit,另外,它们是不可二次赋值的

int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);

ResultHandler 参数允许你按你喜欢的方式处理每一行。你可以将它添加到 List 中、创建 Map 和 Set,或者丢弃每个返回值都可以,它取代了仅保留执行语句过后的总结果列表的死板结果。你可以使用 ResultHandler 做很多事,并且这是 MyBatis 自身内部会使用的方法,以创建结果集列表

package org.apache.ibatis.session;
public interface ResultHandler<T> {
  void handleResult(ResultContext<? extends T> context);
}

ResultContext 参数允许你访问结果对象本身、被创建的对象数目、以及返回值为 Boolean 的 stop 方法,你可以使用此 stop 方法来停止 MyBatis 加载更多的结果
使用 ResultHandler 的时候需要注意以下两种限制:

  • 从被 ResultHandler 调用的方法返回的数据不会被缓存
  • 当使用结果映射集(resultMap)时,MyBatis 大多数情况下需要数行结果来构造外键对象。如果你正在使用 ResultHandler,你可以给出外键(association)或者集合(collection)尚未赋值的对象
批量更新方法

一个方法可以刷新(执行)存储在 JDBC 驱动类中的批量更新语句。当将 ExecutorType.BATCH 作为 ExecutorType 使用时可以采用此方法

List<BatchResult> flushStatements()
事务控制方法
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
本地缓存

Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)
每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询语句本身都会被保存在本地缓存中,那么,相同的查询语句和相同的参数所产生的更改就不会二度影响数据库了。本地缓存会被增删改、提交事务、关闭事务以及关闭 session 所清空。

//清除本地缓存
void clearCache()
确保 SqlSession 被关闭
void close()
使用映射器
<T> T getMapper(Class<T> type)

映射器接口不需要去实现任何接口或继承自任何类。只要方法可以被唯一标识对应的映射语句就可以了

可以传递多个参数给一个映射器方法。如果这样做了,默认情况下它们将会以 “param” 字符串紧跟着它们在参数列表中的位置来命名,比如:#{param1}、#{param2}等。如果想改变参数的名称(只在多参数情况下),那么可以在参数上使用 @Param(“paramName”) 注解。