mybatis 中的 sessionfactory 和 session 的特点和关系?

 我来答
匿名用户
2017-08-14
展开全部
现象1:如果使用原生mybatis进行数据操作,那么必须按照以下方式使用:SqlSessionsqlSession=null;try{sqlSession=sqlSessionFactory.openSession();//namespace+idsqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog",blog);sqlSession.commit(true)}catch(Exceptione){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")publicSqlSessionTemplatesqlSessionTemplate;publicvoidsaveTestTrans(){this.sqlSessionTemplate.selectList("testdomain.selectAnySql","select*frommy_blogwhereid='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的线程安全特性进行了详细的探究:问题2:然后又想到这样一个问题,虽然现在几乎所有项目都使用spring作为java程序的基本框架,如果我不使用spring管理mybatis,仅仅使用原始的mybatis,怎么样才能构建一个和SqlSessionTemplate相似的对象呢?首先想到必须使用java的treadLocal构建一个sqlsession的对象,如ThreadLocalsqlSession=newThreadLocal()。经过查找,发现mybatis自身就有这样一个类实现了类似的功能,类路径:org.apache.ibatis.session.SqlSessionManager,但是没有注释,可能存在mybatis-spring这种神器之后,mybatis放弃了对这个类的维护。该类实现了SqlSessionFactory,SqlSession并且在其中定义了一个treadLocal的sqlssion对象,同时使用了代理拦截进行了sqlsession的自动管理,具体代码可以自己查阅,对于理解mybatis原理和java的代理机制很有帮助。那么写个简单的程序验证一下SqlSessionManager是否真的可以保证线程安全和自动新建和释放sqlssion:TestSqlManager.javaprivatestaticSqlSessionsqlSession;publicstaticSqlSessiongetSqlSessionTest(){if(sqlSession==null){//构建使用的SqlSessionFactorySqlSessionFactorysqlSessionFactory=MyBatisUtil.getSqlSessionFactory();sqlSession=SqlSessionManager.newInstance(sqlSessionFactory);}returnsqlSession;}publicstaticvoidmain(String[]args)throwsInterruptedException{Runrun=newRun();Listthreads=newArrayList();for(inti=0;i<100;i++){Threadt=newThread(run);threads.add(t);System.out.println("thread:{"+t.getName()+"},start");t.start();}for(Threadt:threads){System.out.println("thread:{"+t.getName()+"},join");t.join();}}我本机装的mysql,通过监控语句:selectSUBSTRING_INDEX(host,’:’,1)asip,count(*)frominformation_schema.processlistgroupbyip;发现执行过程中存在连接并发的情况,但是执行之后全部释放掉了。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式