SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession功能域(Scope)和生命周期

MyBatis,  可以说每个MyBatis都是以一个SqlSessionFactory实例为着力的。SqlSessionFactory实例可以经过SqlSessionFactoryBuilder来构建。一是足以透过XML配置文件的法门来构建SqlSessionFactory,二是足以由此Java
API的章程来营造。但不管通过怎么着点子都有一个Configuration贯穿始终,各个配置正是经过Configuration实例来成功完结。

  此篇作品旨在通过编码完毕MyBatis3.4.1 User
Guide所提到的成效域和生命周期指引提议。为何要打听功效域和生命周期呢?在功效域内正确地选取SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession会让大家幸免三十二线程环境下并发所带来的题材。当然即使采纳依赖(DI)注入框架(Spring)可不用在代码中关心功效域难题,因为依靠注入框架会为大家做好大约全体工作。

  首先大家来看User
Guide对SqlSessionFactoryBuilder功效域以及生命周期的点拨意见。

SqlSessionFactoryBuilder

  这些类可以被实例化、使用和丢掉,一旦成立了
SqlSessionFactory,就不再须要它了。由此 SqlSessionFactoryBuilder
实例的最佳范围是方法范围(也就是局地方法变量)。你可以引用
SqlSessionFactoryBuilder 来制造多少个 SqlSessionFactory
实例,不过最为仍然不要让其一贯存在以确保拥有的 XML
解析资源开放给更器重的事务。

SqlSessionFactory

  SqlSessionFactory
一旦被制培育应该在行使的运行时期一向存在,没有任何理由对它举行破除或重建。使用
SqlSessionFactory 的极品实践是在使用运行时期不要再度创造多次,多次重建
SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。因而 SqlSessionFactory 的特等范围是动用范围。有众多办法可以成功,最简便易行的就是应用单例情势或者静态单例方式。

SqlSession

  每个线程都应当有它和谐的 SqlSession 实例。SqlSession
的实例不是线程安全的,由此是不可能被共享的,所以它的最佳的限量是请求或措施范围。相对不可能将
SqlSession
实例的引用位于一个类的静态域,甚至一个类的实例变量也足够。也绝无法将
SqlSession 实例的引用位于其余类型的管理范围中,比如 Serlvet 架构中的
HttpSession。若是你现在正在使用一种 Web 框架,要考虑 SqlSession
放在一个和 HTTP 请求对象一般的限定中。换句话说,每一遍接到的 HTTP
请求,就足以打开一个
SqlSession,重回一个响应,就关门它。那些闭馆操作是很首要的,你应该把那些闭馆操作放到
finally 块中以有限协助每一次都能实施关闭。

  通过User
Guide可以看到官方对SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession的功效域范围分别是:方法范围、应用范围、请求或措施范围。初学者很简单将SqlSessionFactory的效用域范围忽略,而将其和SqlSessionFactoryBuilder和SqlSession都放到方法范围内,那样我并不会推动程序代码错误(只有在将SqlSession置于应用范围才会带来并发性难点),然则那会被认为是“bad
smell”。我在第一篇写《MyBatis3入门》时,就从未仔细阅读User
Guide以至于代码闻起来有一种“坏味道(bad smell)”。例,代码如下:

1 public class SessionFactory {
2     public static SqlSession getSqlSession(String resource) throws IOException{
3         InputStream inputStream = Resources.getResourceAsStream(resource);
4         SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
5         SqlSession sqlSession = sqlSessionFactory.openSession();
6         
7         return sqlSession;
8     }
9 }

  第4行的代码闻起来就有一个“bad
smell”的寓意,因为它的效率不是在方方面面应用范围而是在点子范围。

  而哪些是较好的代码呢?我们应有如上所说,对SqlSessionFactory使用单例情势。重构后的代码如下:

 1 package day_8_mybatis.util;
 2 
 3 import java.io.InputStream;
 4 
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 7 
 8 /**
 9  * @author turbo
10  *
11  * 2016年10月26日
12  */
13 public class SessionFactory2 {
14     private static SqlSessionFactory sqlSessionFactory;
15     
16     public static synchronized SqlSessionFactory getInstance(InputStream inputStream){
17         if (null == sqlSessionFactory){
18             sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
19         }
20         
21         return sqlSessionFactory;
22     }
23 }

  客户端成立SqlSession的代码如下:

 1 package day_8_mybatis;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.session.SqlSession;
 8 
 9 import day_8_mybatis.util.SessionFactory2;
10 
11 /**
12  * 客户端
13  * 
14  * @author turbo
15  *
16  * 2016年10月26日
17  */
18 public class Main {
19 
20     /**
21      * @param args
22      * @throws IOException
23      */
24     public static void main(String[] args) throws Exception {
25         String resource = "day_8_mybatis/mybatis-config.xml"; // 获取mybatis配置文件路径
26         InputStream inputStream = Resources.getResourceAsStream(resource);
27         SqlSession sqlSession = SessionFactory2.getInstance(inputStream).openSession();
28 
29     }
30 
31 }

  那样的代码是还是不是就符合标准,并且看起来舒服多,美丽多了?


这是一个能给程序员加buff的公众号

MyBatis 1

网站地图xml地图