Mybatis source code analysis: SqlSessionManager

SqlSessionManager

   SqlSessionManager itself to achieve a SqlSessionFactory, SqlSession two interfaces, it can build itself Sqlsession and use Sqlsesion declared CURD related query methods. SqlSessionManager constructor can not be instantiated, the method can only be instantiated by newInstance (), in fact, call in SqlSessionFactoryBuilder.build newInstance () method () method instantiates a DefaultSqlsessionFactory. Then instantiated using the constructor.

   Internal SqlSessionManager maintains three properties sqlSessionFactory, sqlSessionProxy, localSqlSession. SqlSessionFactory which role is to participate in the construction of sqlSessionProxy from the following constructor code will know, sqlSessionProxy use of dynamic proxy mode creates a SqlSession proxy object. In the future when CURD related method of operation, will be delegated to the proxy object. The last property localSqlSession maintained by a local thread, thus ensuring the safety of concurrent, in addition to this feature, this property embodies the concept of "nanotubes", after performing startManagedSession () method, will be a corresponding thread SqlSession management, when creating a proxy instance proxy mode, no longer get through opensession () method, but rather directly from the local thread. Other than that difference, SqlSessionManager also provides a method for operating a plurality of additional objects SqlSession native thread. As the following methods:

  • isManagedSessionStarted () to determine whether they are SqlSessionManager regulation, its essence is to determine whether an object is local SqlSeesion thread object in
  • getConnection () Gets the thread from the local connection object
  • Close (); The SqlSession close the thread belongs, and is set to NULL The SqlSession

And code configured SqlSessionManager newInstance () method

 1   private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
 2     this.sqlSessionFactory = sqlSessionFactory;
 3     this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
 4         SqlSessionFactory.class.getClassLoader(),
 5         new Class[]{SqlSession.class},
 6         new SqlSessionInterceptor());
 7   }
 8   //通过InputStream进行实例化
 9   public static SqlSessionManager newInstance(InputStream inputStream, Properties properties) {
10     return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, properties));
11   }
12 //通过SqlSessionFactory 进行实例化
13   public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
14     return new SqlSessionManager(sqlSessionFactory);
15   }
16 //通过Reader进行实例化
17   public static SqlSessionManager newInstance(Reader reader, String environment) {
18     return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));

 

   We know to use JDK dynamic proxy must implement the interface and override InvocationHandler invoke () method, SqlSessionManager constructor when instantiating the proxy class SqlSessionInterceptor class implements the interface InvocationHandler observed invoke () method. invoke try to get the first line of code from a local Sqlsession thread, but if startManagedSession not invoke () method, you never get all null value, that is, each invoke () method to get a new instance by openSession.

. 1   Private  class SqlSessionInterceptor the implements of InvocationHandler {
 2      public SqlSessionInterceptor () {
 . 3          // Prevent to Synthetic Access 
. 4      }
 . 5  
. 6      @Override
 . 7      public Object Invoke (Object Proxy, Method, Method, Object [] args) throws the Throwable {
 . 8          // from native threads acquired acquiring SqlSession, and does not place a thread in the local Sqlsession use SqlSessionManager, examples sqlsession case is null, unless startManagedSession enabled () 
. 9        Final the SqlSession SQLSESSION = SqlSessionManager. the this .localSqlSession.get ();
 10        IF (sqlSession != null) {
11         try {
12           return method.invoke(sqlSession, args);
13         } catch (Throwable t) {
14           throw ExceptionUtil.unwrapThrowable(t);
15         }
16       } else {
17           //通过sqlSessionFactory获取SqlSession
18         final SqlSession autoSqlSession = openSession();
19         try {
20           final Object result = method.invoke(autoSqlSession, args);
21           autoSqlSession.commit();
22           return result;
23         } catch (Throwable t) {
24           autoSqlSession.rollback();
25           throw ExceptionUtil.unwrapThrowable(t);
26         } finally {
27           autoSqlSession.close();
28         }
29       }
30     }
31   }

 

Run one instance

Contrast used startManagedSession () SqlSessionManager and direct method newInstance () test any different. First configure a SqlMapper, there is a list method, students table query student id, name, age, three values.

  • SqlMapper Interface
 1 package com.zzz.mybatis.mapper;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 import org.apache.ibatis.annotations.Flush;
 6 import org.apache.ibatis.annotations.MapKey;
 7 import org.apache.ibatis.annotations.Select;
 8 
 9 public interface SqlMapper {
10     @Select("select id,name,age from student")
11     public List<Map<String, Object>> list();
12 
13     @Flush
14     public void flush();
15 
16     @MapKey(value="id")
17     @Select("select id,name,age from student")
18     public Map<String,Map<String,String>> listByMapkey();
19 }

 

  • Unit test classes
 1 package com.zzz.mybatis.service;
 2 
 3 import org.apache.ibatis.session.SqlSessionManager;
 4 import org.junit.Test;
 5 
 6 public class SqlSessionManagerTest {
 7     @Test
 8     public void SqlSessionManagerByNewInstance() {
 9         SqlSessionManager manager=SqlSessionManager.newInstance(getClass().getResourceAsStream("/mybatis-config.xml"));
10         Object rs=manager.selectOne("com.zzz.mybatis.mapper.SqlMapper.list");
11         System.out.println(rs.toString());
12     }
13 
14     @Test
15     public void SqlSessionManagerByLocalThread() {
16         SqlSessionManager manager=SqlSessionManager.newInstance(getClass().getResourceAsStream("/mybatis-config.xml"));
17         manager.startManagedSession();
18         Object rs=manager.selectOne("com.zzz.mybatis.mapper.SqlMapper.list");
19         System.out.println(rs.toString());
20         rs=manager.selectOne("com.zzz.mybatis.mapper.SqlMapper.list");
21         System.out.println(rs.toString());
22     }
23 
24 }

 

  • operation result
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e853265]
==>  Preparing: select id,name,age from student 
==> Parameters: 
<==    Columns: id, name, age
<==        Row: 1, zhangsan, 22
<==      Total: 1
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@57e1b0c]
==>  Preparing: select id,name,age from student 
==> Parameters: 
<==    Columns: id, name, age
<==        Row: 1, zhangsan, 22
<==      Total: 1

 

Both the differences and connections

   Both are ways to search through the JDK dynamic proxy to achieve, but use a local instance of the internal thread gets SqlSession sqlSessionProxy, a use openSession () method to get SqlSession instance. Use debug observed using a non-manager.startManagedSession (); SqlSession used by the object, can be seen to take a value in localSqlSession NULL, SqlSession Instances must be obtained by openSessiom () method.

  • Using non startManagedSession () generated SqlSession instance

 

If startManagedSession enabled () method, it will get from localSqlSession in SqlSession instance, you can see two of id number is 71, which is twice the query are the same instance.

  • Use startManagedSession () generated SqlSession instance

Guess you like

Origin www.cnblogs.com/zhengzuozhanglina/p/11286130.html