疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

MyBatis 3框架学习SqlSession的前生今世


 

 
在持久层中使用 MyBatis 框架,核心操作就是对 SqlSession 实例对象的操作。下面就详细探索一下 SqlSession 对象的创建及使用。
 
想要获得一个 SqlSession 实例,首先你要有一个 SqlSessionFactory 实例,而要获得 SqlSessionFactory 实例,需要有一个 SqlSessionFactoryBuilder 对象。MyBatis 就为我们提供了这样一个类,来创建我们需要的 SqlSessionFactory 实例,并用来创建 SqlSession 实例。
 
注意,如果使用 Spring 等依赖注入容器, SqlSession 实例的创建会全部交给容器进行管理,这样就不再需要手动创建和管理 SqlSessionFactoryBuilder 和 SqlSessionFactory 了。本文暂不考虑这部分内容。
 
先来看一下 SqlSessionFactoryBuilder 的方法签名:
 
复制代码
1 build(Reader)
2 build(Reader, String)
3 build(Reader, Properties)
4 build(Reader, String, Properties)
5 build(InputStream)
6 build(InputStream, String)
7 build(InputStream, Properties)
8 build(InputStream, String, Properties)
9 build(Configuration)
复制代码
这些方法均会返回一个 SqlSessionFactory 。虽然看上去很多,但实际上只有三个主要方法,其他的都是相应的重载方法。这三个方法接收的参数主要是 Reader ,InputStream ,Configuration ,对应于不同配置文件的读取来源。我们来看一下 build 方法体中的内容:
 
复制代码
 1 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
 2   try {
 3     XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
 4     return build(parser.parse());
 5   } catch (Exception e) {
 6     throw ExceptionFactory.wrapException("Error building SqlSession.", e);
 7   } finally {
 8     ErrorContext.instance().reset();
 9     try {
10       inputStream.close();
11     } catch (IOException e) {
12       // Intentionally ignore. Prefer previous error.
13     }
14   }
15 }
复制代码
这里以 InputStream 为例, Reader 与之类似。这个方法的作用就是将输入流连接的 XML 文件和自定义的环境 environment 、属性 properties 封装成一个 XMLConfigBuilder 对象,再调用该对象的 parse 方法将 XML 及自定义环境和属性转换成一个 Configuration 对象。其中,environment 变量对应配置文件中 <enviroments>  标签下的内容,而 properties 变量则对应配置文件中 <properties> 标签下的内容。关于配置文件,在以后的文章中将详细介绍。
代码 build(parser.parse()) 调用的是 build(Configuration) 这个方法,从这里我们可以看出,SqlSessionFactoryBuilder 的这些方法的最终目的就是生成一个 Configuration 对象,其内部包含所有创建 SqlSessionFactory 所需的配置信息,然后用这些配置信息返回一个 用来提供 SqlSession 实例的 SqlSessionFactory 实例。
 
下面是通过 XML 配置文件获得 SqlSessionFactory 的代码示例:
 
1 String resource = "mybatis-config.xml";
2 // 使用 MyBatis 提供的 Resource 工具类来获取 xml 文件流
3 InputStream in = Resources.getResourceAsStream(resource);
4 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
当然,你可以编写代码直接创建 Configuration 类的实例并传给 SqlSessionFactoryBuilder 来生产 SqlSessionFactory ,这里暂时先不做说明。
 
SqlSessionFactoryBuilder 的本质就是封装了一系列方便创建 SqlSessionFactory 这个重要实例的方法,因此当获得了会话工厂 SqlSessionFactory 之后,SqlSessionFactoryBuilder 的使命就完成了,可以结束它这短暂的一生了。文档中建议一旦获得会话工厂中就废弃 SqlSessionFactoryBuilder 以节省系统资源,它的命运也是够悲惨的。
 
(注:这里涉及到 XML 文件等流的关闭操作,因此尽快释放资源是明智的选择,SqlSessionFactoryBuilder 建议在方法域中使用。)
 
那么,接下来的重心就转移到 SqlSessionFactory 的身上了。这家伙可了不得,一旦被创建出来,将与天地同寿,永远贮存在内存中以供使用,虽然常常一直隐匿于幕后,却是 MyBatis 中非常重要的实例对象。(通常在应用域中以单例或静态单例方式使用。)
 
实际上 SqlSessionFactory 是一个抽象的接口,它规定的方法如下:
 
复制代码
1 openSession()
2 openSession(boolean)
3 openSession(Connection)
4 openSession(TransactionIsolationLevel)
5 openSession(ExecutorType)
6 openSession(ExecutorType, boolean)
7 openSession(ExecutorType, TransactionIsolationLevel)
8 openSession(ExecutorType, Connection)
9 getConfiguration()
复制代码
除了最后一个方法用来获得 Configuration 对象之外,其实都是 openSession 这个方法的重载,目的就是获得具有不同属性的 SqlSession 实例对象。再回头看一眼(最后一眼) SqlSessionFactoryBuilder 中最后一个方法,
 
1 public SqlSessionFactory build(Configuration config) {
2   return new DefaultSqlSessionFactory(config);
3 }
我们可以明确地看到,实际上返回的是 DefaultSqlSessionFactory 这个具体的实现类,同时我们也能看出该类将持有 Configuration 对象的引用。
 
传递的参数基本上是 ExecuterType 、Connection 、TransactionIsolationLevel 、boolean 的多种组合。
 
boolean 值指定是否使用事务的自动提交,默认为 false ,即开启事务但不会自动提交,需要手动 commit ;
Connection 是手动给定一个数据库连接,当不给定时默认在配置的 data source 中自动获取;
TransactionIsolationLevel 是一个枚举类,包含了五种隔离等级,默认是与数据库驱动或 data source 默认配置相同;
ExecuterType 也是一个枚举类,包含 SIMPLE(default) 、REUSE 、BATCH 三个值,REUSE 表示会重用 PreparedStatements ,BATCH 表示批处理更新操作。
可以看出,MyBatis 3 (不同与之前的版本)将数据库相关的操作都整合到了 Session 域中,只需要在创建 Session 的时候将参数指定好就可以了,不需要再单独设置。这也是 SqlSessionFactory 便捷之处。