Mybatis-spring整合對session的理解
Mybatis-spring整合對session的理解
在Mybatis中SqlSessionFactory負責建立SqlSession,一旦建立成功,就可以用SqlSession例項來執行對映語句,commit,rollback,close等方法。但當使用Mybatis-Spring時beans將會注入一個執行緒安全的SqlSession並通過Spring的事務管理自動commit,rollback,close。
通常我們通過對SqlSessionDaoSupport
首先這裡先來看【SqlSessionDaoSupport】的原始碼:
/* * Copyright 2010 The myBatis Team * * Licensed under the Apache License, Version 2.0 (the “License”); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an “AS IS” BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mybatis.spring.support;
imp imp imp imp imp imp
/** * Convenient super class for MyBatis SqlSession da * It gives you access to the template which can then be used to execute SQL methods. * <p> * This class needs a SqlSessionTemplate or a SqlSessionFactory. * If both are set the SqlSessionFactory will be ignored. * * @see #setSqlSessionFactory * @see #setSqlSessionTemplate * @see SqlSessionTemplate * @version
*/ public abstract class SqlSessionDaoSupport extends DaoSupport {
// 這個SqlSession就是我們平時用來執行SQL和事務的一次會話 private SqlSession sqlSession;
private boolean externalSqlSession;
// 可以看到以下兩個Autowired的set方法,實際上他們的功能都是設定sqlSession的例項 // 區別在於一個是通過傳入sqlSessionFactory然後包裝成SqlSessionTemplate // 另一個直接傳入SqlSessionTemplate賦值給sqlSession @Autowired(required = false) public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { if (!this.externalSqlSession) { this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); } }
@Autowired(required = false) public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { this.sqlSession = sqlSessionTemplate; this.externalSqlSession = true; }
/** * Users should use this method to get a SqlSession to call its statement methods * This is SqlSession is managed by spring. Users should not commit/rollback/close it * because it will be automatically done. * * @return Spring managed thread safe SqlSession */ public final SqlSession getSqlSession() { return this.sqlSession; }
/** * {@inheritDoc} */ protected void checkDaoConfig() { Assert.notNull(this.sqlSession, “Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”); }
} |
通過原始碼我們可以看到其實:sqlSessionFactory注入,最終還是被包裝為:sqlSessionTemplate,因此,在繼承SqlSessionDaoSupport類,注入sqlSessionFactory或sqlSessionTemplate,原理上時一致的。
另外通過原始碼的getSession方法的註釋我們可以看到,使用spring管理session,我們不能提交、回滾和關閉session,因為Spring已對其進行執行緒安全管理。
附:spring-mybatis配置檔案:
<!– 配置資料來源 –> <bean id=“dataSource” class=“org.springframework.jndi.JndiObjectFactoryBean”> <property name=“jndiName” value=“java:comp/env/jdbc/bmc” /> <!–property name=”jndiName” value=”bmc” / –> </bean> <!– sqlSessionFactory配置 –> <bean id=“sqlSessionFactory” class=“org.mybatis.spring.SqlSessionFactoryBean”> <property name=“configLocation” value=“classpath:mybatis-config.xml” /> <property name=“mapperLocations” value=“classpath:BMC_*.xml” /> <property name=“dataSource” ref=“dataSource” /> </bean> <!– sqlSessionTemplate配置(支援批量) –> <bean id=“sqlSessionTemplate” class=“org.mybatis.spring.SqlSessionTemplate”> <!– 引數1: sqlSessionFactory|引數2:ExecutorType –> <constructor-arg index=“0” ref=“sqlSessionFactory” /> <constructor-arg index=“1” value=“BATCH” /> </bean> |
注意:
①:在繼承SqlSessionDaoSupport類,無論你是通過[sqlSessionFactory]注入還是通過[sqlSessionTemplate]注入,spring均會對session自動管理,因此您不能通過getSession()獲取的session進行提交、回滾、關閉操作。
②:如果沒繼承SqlSessionDaoSupport類,需要對session自行管理。
總結:
上文僅對繼承SqlSessionDaoSupport類並通過getSession()方法獲取session時,不能對該session進行提交、回滾、關閉操作,因為Spirng已經幫其自動管理。本來文章想說明事務相關的內容,因為在網上看了很多文章說:{使用Mybatis-Spring時beans將會注入一個執行緒安全的SqlSession並通過Spring的事務管理自動commit,rollback,close。},但本人自己除錯程式發現如下日誌:
SqlSessionUtils:46 - Creating a new SqlSession SqlSessionUtils:46 - SqlSession [[email protected]] was not registered for synchronization because synchronization is not active DataSourceUtils:110 - Fetching JDBC Connection from DataSource SpringManagedTransaction:46 - JDBC Connection [jdbc:oracle:thin:@127.0.0.1:1521:bmcdb, UserName=BMC, Oracle JDBC driver] will not be managed by Spring findRescByRoleID:46 - ooo Using Connection [jdbc:oracle:thin:@127.0.0.1:1521:bmcdb, UserName=BMC, Oracle JDBC driver] findRescByRoleID:46 - ==> Preparing: SELECT R.RESCID,R.RESCTYPE,R.RESCNAME,R.RESCURL FROM BMC_RESOURCE R LEFT JOIN BMC_ROLE_RESOURCE RR ON R.RESCID = RR.RESCID WHERE RR.ROLEID = ? findRescByRoleID:46 - ==> Parameters: ST00004G(String) findRescByRoleID:46 - <== Total: 0 SqlSessionUtils:46 - Closing non transactional SqlSession [[email protected]] DataSourceUtils:327 - Returning JDBC Connection to DataSource |
通過日誌的紅色部分,我們可以看到,其含義為:
①:【SqlSession: was not registered for synchronization because synchronization is not active】同步未註冊,因為同步是不可行的;
②:【JDBC Connection:will not be managed by Spring】事務沒有被Spring管理;
③:【Closing non transactional SqlSession】關閉沒有非事務的SqlSession。
但如果對datasource在spring 配置檔案中加入事務管理配置,上述日誌將會有變化,但由於自己還沒有弄懂,所以這裡先不做說明,待自己弄懂之後再進述。