mybatis 线程安全问题

来源:互联网 发布:卖家淘宝客怎么设置 编辑:程序博客网 时间:2024/05/29 03:02

现象1:如果使用原生mybatis进行数据操作,那么必须按照以下方式使用:

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

问题1:

那么问题来了,为什么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

0 0
原创粉丝点击