日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mybatis--MapperProxy事务

發布時間:2023/12/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mybatis--MapperProxy事务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上篇?詳細分析了org.mybatis.spring.mapper.MapperScannerConfigurer?和 org.mybatis.spring.SqlSessionFactoryBean的作用,可以直接看最后的總結

MapperFactoryBean是mapper接口的入口,它包含了sqlSessionFactory的封裝SqlSessionTemplate,而sqlSessionFactory又包含了mapper xml的組裝Configuration對象

從SqlSessionTemplate的

public <T> T getMapper(Class<T> type) {
return this.getConfiguration().getMapper(type, this);
}

開始,進入Configuration的getMapper(type,sqlsession)

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return this.mapperRegistry.getMapper(type, sqlSession);
}

進入MapperRegistry

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if(mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
}

由MapperProxyFactory生成代理MapperProxy

protected T newInstance(MapperProxy<T> mapperProxy) {
return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}

public T newInstance(SqlSession sqlSession) {
MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
return this.newInstance(mapperProxy);
}

所以最終的調用會進入MapperProxy,接下來幾步在?mybatis緩存?中有介紹,會調用sqlSession(實際是SqlSessionTemplate)中的方法,看構造方法:

public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {Assert.notNull(sqlSessionFactory, "Property \'sqlSessionFactory\' is required");Assert.notNull(executorType, "Property \'executorType\' is required");this.sqlSessionFactory = sqlSessionFactory;this.executorType = executorType;this.exceptionTranslator = exceptionTranslator;this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());}

會對SqlSessionFactory生成代理,實際調用這個代理的方法

public <T> T selectOne(String statement) {
return this.sqlSessionProxy.selectOne(statement);
}

1. 進入SqlSessionTemplate.SqlSessionInterceptor

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
   ......
Object t = method.invoke(sqlSession, args);
......
}

看SqlSessionUtils.getSqlSession方法:

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {Assert.notNull(sessionFactory, "No SqlSessionFactory specified");Assert.notNull(executorType, "No ExecutorType specified");SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);if(holder != null && holder.isSynchronizedWithTransaction()) {if(holder.getExecutorType() != executorType) {throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");} else {holder.requested();if(logger.isDebugEnabled()) {logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");}return holder.getSqlSession();}} else {//進入這里呀呀呀if(logger.isDebugEnabled()) {logger.debug("Creating a new SqlSession");}
       //step 1.1SqlSession session
= sessionFactory.openSession(executorType);if(TransactionSynchronizationManager.isSynchronizationActive()) {Environment environment = sessionFactory.getConfiguration().getEnvironment();if(environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {if(logger.isDebugEnabled()) {logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");}//step 1.2holder = new SqlSessionHolder(session, executorType, exceptionTranslator);TransactionSynchronizationManager.bindResource(sessionFactory, holder);TransactionSynchronizationManager.registerSynchronization(new SqlSessionUtils.SqlSessionSynchronization(holder, sessionFactory));holder.setSynchronizedWithTransaction(true);holder.requested();} else {if(TransactionSynchronizationManager.getResource(environment.getDataSource()) != null) {throw new TransientDataAccessResourceException("SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");}if(logger.isDebugEnabled()) {logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");}}} else if(logger.isDebugEnabled()) {logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");}return session;}}

1.1 進入DefaultSqlSessionFactory openSession方法:

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;DefaultSqlSession var8;try {Environment e = this.configuration.getEnvironment();
//springManagedTransactionFactoryTransactionFactory transactionFactory
= this.getTransactionFactoryFromEnvironment(e);tx = transactionFactory.newTransaction(e.getDataSource(), level, autoCommit);Executor executor = this.configuration.newExecutor(tx, execType, autoCommit);var8 = new DefaultSqlSession(this.configuration, executor);} catch (Exception var12) {this.closeTransaction(tx);throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);} finally {ErrorContext.instance().reset();}return var8;}

進入SpringManagedTransactionFactory的

newTransaction(e.getDataSource(), level, autoCommit);

返回

return new SpringManagedTransaction(dataSource);

這個SpringManagedTransaction比較特別,因為

private void openConnection() throws SQLException {
this.connection = DataSourceUtils.getConnection(this.dataSource);
this.autoCommit = this.connection.getAutoCommit();
this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
if(this.logger.isDebugEnabled()) {
this.logger.debug("JDBC Connection [" + this.connection + "] will" + (this.isConnectionTransactional?" ":" not ") + "be managed by Spring");
}
}

因為它的連接來自DataSourceUtils

public static Connection doGetConnection(DataSource dataSource) throws SQLException {Assert.notNull(dataSource, "No DataSource specified");ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);if(conHolder == null || !conHolder.hasConnection() && !conHolder.isSynchronizedWithTransaction()) {logger.debug("Fetching JDBC Connection from DataSource");Connection con = dataSource.getConnection();if(TransactionSynchronizationManager.isSynchronizationActive()) {logger.debug("Registering transaction synchronization for JDBC Connection");ConnectionHolder holderToUse = conHolder;if(conHolder == null) {holderToUse = new ConnectionHolder(con);} else {conHolder.setConnection(con);}holderToUse.requested();TransactionSynchronizationManager.registerSynchronization(new DataSourceUtils.ConnectionSynchronization(holderToUse, dataSource));holderToUse.setSynchronizedWithTransaction(true);if(holderToUse != conHolder) {TransactionSynchronizationManager.bindResource(dataSource, holderToUse);}}return con;} else {conHolder.requested();if(!conHolder.hasConnection()) {logger.debug("Fetching resumed JDBC Connection from DataSource");conHolder.setConnection(dataSource.getConnection());}return conHolder.getConnection();}}

這一步就和?spring--事務原理?中分析的對接了!!!connection連接對象來自當前線程綁定的ConnectionHolder中的connection對象

最終?DefaultSqlSession-》Executor-》Transaction-》當前線程綁定的ConnectionHolder中的connection對象?

1.2 構建SqlSessionHolder-》DefaultSqlSession,并綁定到當前線程<sessionFactory,session holder>

2. DefaultSqlSession的執行見??mybatis緩存?

?

轉載于:https://www.cnblogs.com/yhzh/p/5588390.html

總結

以上是生活随笔為你收集整理的mybatis--MapperProxy事务的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。