Mybatis sqlsessiontemplate Source Code Analysis

Source: Internet
Author: User
Tags throwable

This digest from http://www.cnblogs.com/daxin/p/3544188.html

We used the Sqlsessiontemplate class when using MyBatis to integrate with spring.

    <bean id= "sqlsession" class= "org.mybatis.spring.SqlSessionTemplate" >          <constructor-arg index= "0" ref= " Sqlsessionfactory "/>    </bean>

Through the source of how we see sqlsessiontemplate implementation of the Sqlsession interface, that is, we can use Sqlsessiontemplate to proxy the previous defailtsqlsession to complete the operation of the database, But defailtsqlsession this class is not thread-safe, so this class cannot be set to singleton mode.

If it's a normal development model, we can get one from sqlsessionfactory each time we use defailtsqlsession. However, with spring integration, Spring provides a globally unique sqlsessiontemplate example to complete the functionality of defailtsqlsession, the problem is: whether multiple DAO uses a sqlsessiontemplate, Or a DAO using a sqlsessiontemplate,sqlsessiontemplate is a sqlsession, and when multiple Web threads invoke the same DAO, they use the same sqlsessiontemplate , which is the same sqlsession, how does it ensure thread safety? Let's analyze it together.

(1) First, the proxy class is created by the following code, representing an instance of the proxy class that created the Sqlsessionfactory, which implements the Sqlsession interface, defines the method interceptor, and if the method that implements the Sqlsession interface definition is called in the proxy class instance, The call is directed to the Sqlsessioninterceptor Invoke method

1 public   sqlsessiontemplate (sqlsessionfactory sqlsessionfactory, Executortype executortype, 2       Persistenceexceptiontranslator exceptiontranslator) {3  4     notnull (sqlsessionfactory, "property" Sqlsessionfactory ' is required "); 5     notnull (Executortype, "Property ' Executortype ' is required"); 6  7     this.sqlsessionfactory = Sqlsessionfactory; 8     this.executortype = executortype; 9     this.exceptiontranslator = exceptiontranslator;10     This.sqlsessionproxy = (sqlsession) newproxyinstance (         SqlSessionFactory.class.getClassLoader (),         new Class[] {sqlsession.class},13         new Sqlsessioninterceptor ());   

The core code is in the Sqlsessioninterceptor invoke method.

 1 Private class Sqlsessioninterceptor implements Invocationhandler {2 public object invoke (object proxy, Method me Thod, object[] args) throws Throwable {3//Get Sqlsession (this sqlsession is really used, it is not thread-safe) 4//This method can be based on spring things up and down Text to get the sqlsession within the range of things 5//A will we analyze This method 6 final sqlsession sqlsession = getsqlsession (7 sqlsessiontemp Late.this.sqlSessionFactory, 8 SqlSessionTemplate.this.executorType, 9 SqlSessionTemplate.this.excepti         Ontranslator); try {11//Call real sqlsession method, Object result = Method.invoke (sqlsession, args); 13 Then determine if the current sqlsession is hosted by spring and automatically commit14 if not hosted by spring (!issqlsessiontransactional (sqlsession, Sqlsessi OnTemplate.this.sqlSessionFactory) {//force commit even on Non-dirty sessions because some databases Requir E16//A commit/rollback before calling close () Sqlsession.commit (true); 18}19//Return Line result return resULT;21} catch (Throwable t) {22//If an exception occurs, the conversion is thrown after the throwable unwrapped = unwrapthrowable (t); 24           if (SqlSessionTemplate.this.exceptionTranslator! = null && unwrapped instanceof persistenceexception) {25 Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible ((persistenceexcep         tion) unwrapped); if (translated! = null) {unwrapped = translated;28}29}30 Throw Unwrapped;31} finally {32//close SQLSESSION33//It will be executed depending on whether the current sqlsession is in the context of the spring. Close Action 34//If Sqlsession is managed by spring, call holder.released ();       Make counter-135//otherwise really close sqlSession36 closesqlsession (sqlsession, SqlSessionTemplate.this.sqlSessionFactory); 37 }38}39}

In the above Invoke method, two tool methods are used, namely

Sqlsessionutils.getsqlsession (sqlsessionfactory sessionfactory, Executortype Executortype, Persistenceexceptiontranslator exceptiontranslator)

Sqlsessionutils.closesqlsession (sqlsession session, Sqlsessionfactory Sessionfactory)

So how do these two methods relate to the things of spring?

 1 public static sqlsession getsqlsession (Sqlsessionfactory sessionfactory, Executortype Executortype, Persistenceexceptiontranslator exceptiontranslator) {2//sqlsessionfactory gets sqlsessionholder from the resource map corresponding to the current thread, as sq     Lsessionfactory The sqlsession is created, a pair of mappings is added to the transaction manager: The key is sqlsessionfactory,value to Sqlsessionholder, and the class saves sqlsession and execution mode 3  Sqlsessionholder holder = (sqlsessionholder) getresource (sessionfactory); 4//If holder is not empty and is synchronized with the current transaction 5 if (Holder! = null && holder.issynchronizedwithtransaction ()) {6//hodler An exception is thrown when the execution type of the save is inconsistent with the execution type of get sqlsession, that is, the execution type cannot change in the same transaction because the sqlsession created by the same sqlsessionfactory in the same transaction will be reused 7 if ( Holder.getexecutortype ()! = Executortype) {8 throw new transientdataaccessresourceexception ("Cannot change the E  Xecutortype when there was an existing transaction "); 9} 10//Increase the holder, that is, the unique sqlsession created by the same sqlsessionfactory in the same transaction, the number of references increases, the number of times it is used increases by one holder.requested (); 12//returns sqlsession return Holder.getSqlsession (); 14} 15//If not found, a new sqlsession sqlsession session = Sessionfactory.opensession (Executortype) is constructed according to the execution type; 17//Determine if synchronization is active, as long as SPRINGTX is activated, is true if (issynchronizationactive ()) {19//Load environment variable, determine whether the registered transaction manager is Springmanagedtrans Action, the Spring Management transaction, Environment environment = Sessionfactory.getconfiguration (). Getenvironment (); if (Environment.gettransactionfactory () instanceof springmanagedtransactionfactory) {22//If yes, the sqlsession will be loaded into the Holder = new Sqlsessionholder (Session, Executortype, Exceptiontranslator) in the local thread cache for service management; 24//With Sessionfactory for Key,hodler as value, added to Transactionsynchronizationmanager managed local cache Threadlocal<map<object, object>> Resources in Bindresource (sessionfactory, Holder); 26//Holder, Sessionfactory synchronization is added to the local thread cache threadlocal<set<transactionsynchronization>> synchronizations Registersynchronization (new sqlsessionsynchronization (holder, sessionfactory)); 28//Set current holder and currentTransaction synchronization holder.setsynchronizedwithtransaction (TRUE); 30//Increase quoted number of holder.requested (); + Else {getresource (environment.getdatasource () = = null) {thro} else { W New Transientdataaccessresourceexception (Sqlsessionfactory must be using a SPRINGMANAGEDTRANSACTIONFA Ctory in order to use Spring transaction synchronization "); (PNS}), or else {+}, return session;  42}
1 public static void Closesqlsession (sqlsession session, Sqlsessionfactory sessionfactory) {  2  // In fact, the following is to determine whether the session is spring transaction management, if management will get holder   3     sqlsessionholder holder = (sqlsessionholder) getresource ( Sessionfactory);  4     if ((Holder! = null) && (holder.getsqlsession () = = session)) {  5    //The function here is released, not closed, just reduce the number of references, Because the back may be reused  6       holder.released ();  7     } else {  8    //If it is not managed by spring, then it will not be closed by spring, it will need to close  9       session.close (); 10     

Mybatis sqlsessiontemplate Source Code Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.