单纯使用Mybatis框架 如何构建线程安全的SqlSession
2016-11-23 14:40
489 查看
现象1:如果使用原生mybatis进行数据操作,那么必须按照以下方式使用:
也就是要像原始的java.sql.Connection对象一样,必须按照:新建连接->执行SQL->提交(查询不需要)->如果操作数据存在异常需要回滚->释放数据库连接。注意第一点和最后一点,每个SqlSession新建之后必须释放,不然会造成数据库连接泄露的危险。也就是意味着SqlSession是个有状态的对象,是无法进行复用的,所以只能局限于request或者方法的范围,也就是所谓的线程不安全。
现象2:如果使用spring集成mybatis,官方提供了整和包mybatis-spring.jar,如果完成配置之后,使用方式及其简单,简单示例如下:
这里的SqlSessionTemplate不仅是单例的,而且不需要手工新建和关闭SqlSession
可以看到使用spring整合Mybatis框架特别方便,但是当我们不想使用spring框架时如何得到线程安全的SqlSession呢???
为什么mybatis-spring.jar中的SqlSessionTemplate可以被多个dao复用,而且不会造成数据连接泄露呢,并且还可以自动新建和释放数据库连接?
官方解答是因为SqlSessionTemplate是线程安全的,也就是确保每个线程使用的sqlSession的唯一并不互相冲突。
首先看了一下mybatis-spring的源码,发现SqlSessionTemplate是通过代理拦截和SqlSessionHolder实现的sqlsession线程安全和自动新建和释放连接的。看构造函数函数中构建代理类,该代理类实现SqlSession接口,定义了方法拦截器,如果调用代理类实例中实现SqlSession接口定义的方法,该调用则被导向SqlSessionInterceptor的invoke方法,这个方法中自动进行了SqlSession的自动请求和释放(如果不被spring托管则自己新建和释放sqlsession,如果被spring管理则使用SqlSessionHolder进行request和relase操作)
以下网址针对SqlSessionTemplate的线程安全特性进行了详细的探究:http://www.cnblogs.com/daxin/p/3544188.html
仅仅使用原始的mybatis,怎么样才能构建一个和SqlSessionTemplate相似的对象呢?
首先想到必须使用java的treadLocal构建一个sqlsession的对象,如ThreadLocal sqlSession = new ThreadLocal()。
经过查找,发现mybatis自身就有这样一个类实现了类似的功能,类路径:org.apache.ibatis.session.SqlSessionManager,但是没有注释,可能存在mybatis-spring这种神器之后,mybatis放弃了对这个类的维护。
该类实现了SqlSessionFactory, SqlSession并且在其中定义了一个treadLocal的sqlssion对象,同时使用了代理拦截进行了sqlsession的自动管理,具体代码可以自己查阅,对于理解mybatis原理和java的代理机制很有帮助。
那么写个简单的程序验证一下SqlSessionManager是否真的可以保证线程安全和自动新建和释放
sqlssion:TestSqlManager.java
我本机装的mysql,通过监控语句:
;发现执行过程中存在连接并发的情况,但是执行之后全部释放掉了。
SqlSession sqlSession = null; try { sqlSession = sqlSessionFactory.openSession(); //namespace+id sqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog", blog); sqlSession.commit(true) } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(true); } finally { sqlSession.close(); }
也就是要像原始的java.sql.Connection对象一样,必须按照:新建连接->执行SQL->提交(查询不需要)->如果操作数据存在异常需要回滚->释放数据库连接。注意第一点和最后一点,每个SqlSession新建之后必须释放,不然会造成数据库连接泄露的危险。也就是意味着SqlSession是个有状态的对象,是无法进行复用的,所以只能局限于request或者方法的范围,也就是所谓的线程不安全。
现象2:如果使用spring集成mybatis,官方提供了整和包mybatis-spring.jar,如果完成配置之后,使用方式及其简单,简单示例如下:
//注入spring中配置的SqlSessionTemplate对象,单例 @Resource(name="sqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate; public void saveTestTrans(){ this.sqlSessionTemplate.selectList("testdomain.selectAnySql", "select * from my_blog where id='1'"); }
这里的SqlSessionTemplate不仅是单例的,而且不需要手工新建和关闭SqlSession
可以看到使用spring整合Mybatis框架特别方便,但是当我们不想使用spring框架时如何得到线程安全的SqlSession呢???
为什么mybatis-spring.jar中的SqlSessionTemplate可以被多个dao复用,而且不会造成数据连接泄露呢,并且还可以自动新建和释放数据库连接?
官方解答是因为SqlSessionTemplate是线程安全的,也就是确保每个线程使用的sqlSession的唯一并不互相冲突。
首先看了一下mybatis-spring的源码,发现SqlSessionTemplate是通过代理拦截和SqlSessionHolder实现的sqlsession线程安全和自动新建和释放连接的。看构造函数函数中构建代理类,该代理类实现SqlSession接口,定义了方法拦截器,如果调用代理类实例中实现SqlSession接口定义的方法,该调用则被导向SqlSessionInterceptor的invoke方法,这个方法中自动进行了SqlSession的自动请求和释放(如果不被spring托管则自己新建和释放sqlsession,如果被spring管理则使用SqlSessionHolder进行request和relase操作)
以下网址针对SqlSessionTemplate的线程安全特性进行了详细的探究:http://www.cnblogs.com/daxin/p/3544188.html
仅仅使用原始的mybatis,怎么样才能构建一个和SqlSessionTemplate相似的对象呢?
首先想到必须使用java的treadLocal构建一个sqlsession的对象,如ThreadLocal sqlSession = new ThreadLocal()。
经过查找,发现mybatis自身就有这样一个类实现了类似的功能,类路径:org.apache.ibatis.session.SqlSessionManager,但是没有注释,可能存在mybatis-spring这种神器之后,mybatis放弃了对这个类的维护。
该类实现了SqlSessionFactory, SqlSession并且在其中定义了一个treadLocal的sqlssion对象,同时使用了代理拦截进行了sqlsession的自动管理,具体代码可以自己查阅,对于理解mybatis原理和java的代理机制很有帮助。
那么写个简单的程序验证一下SqlSessionManager是否真的可以保证线程安全和自动新建和释放
sqlssion:TestSqlManager.java
private static SqlSession sqlSession; public static SqlSession getSqlSessionTest(){ if(sqlSession == null){ //构建使用的SqlSessionFactory SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory(); sqlSession = SqlSessionManager.newInstance(sqlSessionFactory); } return sqlSession; } public static void main(String[] args) throws InterruptedException { Run run = new Run(); List threads = new ArrayList(); for (int i = 0; i < 100; i++) { Thread t = new Thread(run); threads.add(t); System.out.println("thread:{"+t.getName()+"}, start"); t.start(); } for (Thread t : threads) { System.out.println("thread:{"+t.getName()+"},join"); t.join(); } }
我本机装的mysql,通过监控语句:
select SUBSTRING_INDEX(host,’:’,1) as ip , count(*) from information_schema.processlist group by ip
;发现执行过程中存在连接并发的情况,但是执行之后全部释放掉了。
相关文章推荐
- 如何使用Maven和eclipse构建大数据开发框架项目
- Android开发培训之如何使用该框架来构建自己的应用
- 如何使用Maven和eclipse构建大数据开发框架项目
- SSM框架使用Maven构建环境详细整合教程(Spring+SpringMVC+MyBatis)
- 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(61)-如何使用框架来开发?
- J2EE项目系列(四)--SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis)(3)Ajax使用详解(级联列表)以及企业级报表Excel导入导出实现
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
- Java并发框架——AQS之如何使用AQS构建同步器
- 构建微服务:如何优雅的使用mybatis
- MyBatis中如何合理的使用EhCache缓存框架
- 构建微服务:如何优雅的使用mybatis
- spring-boot+mybatis开发实战:如何在spring-boot中使用myabtis持久层框架
- 如何构建mybatis线程安全的sqlsession对象
- 使用maven构建ssm(spring+springmvc+mybatis)框架
- Java并发框架——AQS之如何使用AQS构建同步器
- 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序
- 使用 IBM Rational Functional Tester测试 Windows 应用程序: 如何构建结构良好的测试框架
- 构建一个使用mybatis框架的项目
- jdk1.4 构建 java多线程,并发设计框架 使用列子(六)
- jdk1.4 构建 java多线程,并发设计框架 使用列子(二)