|
This post has NOT been accepted by the mailing list yet.
nice to meet you !
> > when two dao functions use different ExecutorType and it is in a transaction,The above problems occur. > I have learned that the root cause is " TransactionSynchronizationManager.bindResource(sessionFactory, holder);". > It's key is sessionFactory,but not sessionFactory+ExecutorType.why can't we set the key as above? what's more,I don't find the Bad places with this way. > sorry for my poor english,I hope you can realize. > I want to know what's think over the way now! > > these are my code: > > public class MybatisBindObject { > private SqlSessionFactory sqlSessionFactory; > private ExecutorType executorType; > > private MybatisBindObject(SqlSessionFactory sqlSessionFactory, > ExecutorType executorType) { > Assert.notNull(sqlSessionFactory, "No SqlSessionFactory specified"); > Assert.notNull(executorType, "No ExecutorType specified"); > this.sqlSessionFactory = sqlSessionFactory; > this.executorType = executorType; > } > > @Override > public boolean equals(Object obj) { > if (!(obj instanceof MybatisBindObject)) > return false; > MybatisBindObject bindObject = (MybatisBindObject) obj; > return this.sqlSessionFactory.equals(bindObject.sqlSessionFactory) > && this.executorType.equals(bindObject.executorType); > } > > @Override > public int hashCode() { > return this.sqlSessionFactory.hashCode()*this.executorType.hashCode()+473; > } > > public static MybatisBindObject getMybatisBindObject(SqlSessionFactory sqlSessionFactory, > ExecutorType executorType){ > return new MybatisBindObject(sqlSessionFactory,executorType); > } > } > > -------------------------------- > --SqlSessionUtils-- > > > public static SqlSession getSqlSession( > SqlSessionFactory sessionFactory, > ExecutorType executorType, > PersistenceExceptionTranslator exceptionTranslator) { > > Assert.notNull(sessionFactory, "No SqlSessionFactory specified"); > Assert.notNull(executorType, "No ExecutorType specified"); > MybatisBindObject bindObject = MybatisBindObject.getMybatisBindObject(sessionFactory, executorType); > SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(bindObject); > > if (holder != null && holder.isSynchronizedWithTransaction()) { > if (holder.getExecutorType() != executorType) { > throw new TransientDataAccessResourceException( > "Cannot change the ExecutorType when there is an existing transaction"); > } > > holder.requested(); > > if (logger.isDebugEnabled()) { > logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction"); > } > > return holder.getSqlSession(); > } > > DataSource dataSource = sessionFactory.getConfiguration().getEnvironment().getDataSource(); > > // SqlSessionFactoryBean unwraps TransactionAwareDataSourceProxies but > // we keep this check for the case that SqlSessionUtils is called from custom code > boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy); > Connection conn; > try { > conn = transactionAware ? dataSource.getConnection() : DataSourceUtils.getConnection(dataSource); > } catch (SQLException e) { > throw new CannotGetJdbcConnectionException("Could not get JDBC Connection for SqlSession", e); > } > > if (logger.isDebugEnabled()) { > logger.debug("Creating SqlSession with JDBC Connection [" + conn + "]"); > } > > // Assume either DataSourceTransactionManager or the underlying > // connection pool already dealt with enabling auto commit. > // This may not be a good assumption, but the overhead of checking > // connection.getAutoCommit() again may be expensive (?) in some drivers > // (see DataSourceTransactionManager.doBegin()). One option would be to > // only check for auto commit if this function is being called outside > // of DSTxMgr, but to do that we would need to be able to call > // ConnectionHolder.isTransactionActive(), which is protected and not > // visible to this class. > SqlSession session = sessionFactory.openSession(executorType, conn); > > // Register session holder and bind it to enable synchronization. > // > // Note: The DataSource should be synchronized with the transaction > // either through DataSourceTxMgr or another tx synchronization. > // Further assume that if an exception is thrown, whatever started the transaction will > // handle closing / rolling back the Connection associated with the SqlSession. > if (TransactionSynchronizationManager.isSynchronizationActive()) { > if (!(sessionFactory.getConfiguration().getEnvironment().getTransactionFactory() instanceof SpringManagedTransactionFactory) > && DataSourceUtils.isConnectionTransactional(conn, dataSource)) { > throw new TransientDataAccessResourceException( > "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"); > } > > if (logger.isDebugEnabled()) { > logger.debug("Registering transaction synchronization for SqlSession [" + session + "]"); > } > holder = new SqlSessionHolder(session, executorType, exceptionTranslator); > TransactionSynchronizationManager.bindResource(bindObject, holder); > TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory,executorType)); > holder.setSynchronizedWithTransaction(true); > holder.requested(); > } else { > if (logger.isDebugEnabled()) { > logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active"); > } > } > > return session; > } > ---------------------------- > > > wait for your reply! thanks! |
| Powered by Nabble | Edit this page |
