提供一些静态方法用于管理可能参与事务的JDBC连接。JDBCTemplate 或JDBCDaoSupport自动使用它,而且在DataSourceTransactionManager或JTATransactionManager,hibernateTransactionManager中支持。 DataSourceTransactionManager中 DataSourceTransactionManager.DataSourceTransactionObject在事务开始时存储连接,事务完结后使用它获取连接以回复只读,隔离级别及释放连接。在事务挂起和回复时只是解除或重新绑定Holder到当前线程。 成员变量 newConnectionHolder:ConnectionHolder是否为DataSourceTransactionManager doBegin创建。true说明由事务管理器创建,那么在doBegin方法中获取连接并将Holder绑定到线程,在事务完结后由doCleanupAfterCompletion方法接触Holder绑定并释放连接。 mustRestoreAutoCommit:在事务开始时保存连接自动提交模式,进入Spring事务管理将禁用连接自动提交模式,当事务完结后doCleanupAfterCompletion将回复Spring管理之前连接的自动提交模式(无论是禁用的还是启用的:虽然很多数据源提供了自动连接模式,但Spring要求必须禁用)。 方法 hasTransaction 由connectionHolder.isTransactionActive决定,事务开始时设置,完结后清除 setRollbackOnly 设置本地只读标志,AbstractPlatformTransactionManager中提到 /** * DataSource transaction object, representing a ConnectionHolder. * Used as transaction object by DataSourceTransactionManager. */ private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport { private boolean newConnectionHolder; private boolean mustRestoreAutoCommit; public void setConnectionHolder(ConnectionHolder connectionHolder, boolean newConnectionHolder) { super.setConnectionHolder(connectionHolder); this.newConnectionHolder = newConnectionHolder; } public boolean isNewConnectionHolder() { return this.newConnectionHolder; } public boolean hasTransaction() { return (getConnectionHolder() != null && getConnectionHolder().isTransactionActive()); } public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) { this.mustRestoreAutoCommit = mustRestoreAutoCommit; } public boolean isMustRestoreAutoCommit() { return this.mustRestoreAutoCommit; } public void setRollbackOnly() { getConnectionHolder().setRollbackOnly(); } public boolean isRollbackOnly() { return getConnectionHolder().isRollbackOnly(); } } DataSourceUtils.ConnectionSynchronization主要用于JTATransactionManager的资源挂起,回复,资源清理;也支持其它应用的资源清理操作。 方法 suspend 事务挂起时调用,除了解绑资源更重要的是尽可能早的释放连接,DataSourceUtils可重新获取新的连接并绑定到Holder beforeCompletion 事务提交或回滚之前调用,解绑资源和尽可能早的释放连接,当连接被其他应用释放掉DataSourceUtils.releaseConnection(JTA规范规定事务处理完成后,必须关闭所有资源) afterCompletion 事务提交或回滚之后调用,在JTATransactionManager支持下,对于参与性事务该方法被注册到J2EE事务管理器上由JTA事务完成后执行,有可能与在一个不同于当前线程的线程中执行,那Holder便不可解除。所以我们必须将连接置空。而且在事务完成之后将事务状态:同步只读事务超时引用全部清空。 /** * Callback for resource cleanup at the end of a non-native JDBC transaction * (e.g. when participating in a JtaTransactionManager transaction). * @see org.springframework.transaction.jta.JtaTransactionManager */ private static class ConnectionSynchronization extends TransactionSynchronizationAdapter { private final ConnectionHolder connectionHolder; private final DataSource dataSource; private int order; private boolean holderActive = true; public ConnectionSynchronization(ConnectionHolder connectionHolder, DataSource dataSource) { this.connectionHolder = connectionHolder; this.dataSource = dataSource; this.order = getConnectionSynchronizationOrder(dataSource); } @Override public int getOrder() { return this.order; } @Override public void suspend() { if (this.holderActive) { TransactionSynchronizationManager.unbindResource(this.dataSource); if (this.connectionHolder.hasConnection() && !this.connectionHolder.isOpen()) { // Release Connection on suspend if the application doesn't keep // a handle to it anymore. We will fetch a fresh Connection if the // application accesses the ConnectionHolder again after resume, // assuming that it will participate in the same transaction. releaseConnection(this.connectionHolder.getConnection(), this.dataSource); this.connectionHolder.setConnection(null); } } } @Override public void resume() { if (this.holderActive) { TransactionSynchronizationManager.bindResource(this.dataSource, this.connectionHolder); } } @Override public void beforeCompletion() { // Release Connection early if the holder is not open anymore // (that is, not used by another resource like a Hibernate Session // that has its own cleanup via transaction synchronization), // to avoid issues with strict JTA implementations that expect // the close call before transaction completion. if (!this.connectionHolder.isOpen()) { TransactionSynchronizationManager.unbindResource(this.dataSource); this.holderActive = false; if (this.connectionHolder.hasConnection()) { releaseConnection(this.connectionHolder.getConnection(), this.dataSource); } } } @Override public void afterCompletion(int status) { // If we haven't closed the Connection in beforeCompletion, // close it now. The holder might have been used for other // cleanup in the meantime, for example by a Hibernate Session. if (this.holderActive) { // The thread-bound ConnectionHolder might not be available anymore, // since afterCompletion might get called from a different thread. TransactionSynchronizationManager.unbindResourceIfPossible(this.dataSource); this.holderActive = false; if (this.connectionHolder.hasConnection()) { releaseConnection(this.connectionHolder.getConnection(), this.dataSource); // Reset the ConnectionHolder: It might remain bound to the thread. this.connectionHolder.setConnection(null); } } this.connectionHolder.reset(); } } JTATransactionManager支持下无论事务开始,挂起,回复,完成都与资源操作无关(这是JTA事务具备而本地事务不具备的优点)。在应用中可调用JdbcTemplate或JDBCDaoSupport或DataSourceUtils。在Spring同步激活下,初次调用DataSourceUtils.getConnection时,会注册DataSourceUtils.ConnectionSynchronization实例。hibernateTransactionManager支持下当检测到javax.sql.DataSource时会绑定新的ConnectionHolder,它的connection是由Session提供的因此他只是一个连接代理,没有权利也不必关心连接的释放。只有刚获取的连接才有资格由ConnectionSynchronization资源释放。其它应用与之类似。 方法 doGetConnection获取JDBC连接 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())) { //如果Holder被绑定着,并且能使用连接或者Holder作为事务管理器开启事务或Spring同步所管理,这种情况可视为连接可重新获取。 conHolder.requested(); if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(dataSource.getConnection()); } return conHolder.getConnection(); } // Else we either got no holder or an empty thread-bound holder here. logger.debug("Fetching JDBC Connection from DataSource"); //获取新的连接 Connection con = dataSource.getConnection(); //spring同步激活了,可用同步实例管理资源 if (TransactionSynchronizationManager.isSynchronizationActive()) { logger.debug("Registering transaction synchronization for JDBC Connection"); // Use same Connection for further JDBC actions within the transaction. // Thread-bound object will get removed by synchronization at transaction completion. ConnectionHolder holderToUse = conHolder; if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } else { holderToUse.setConnection(con); } holderToUse.requested(); TransactionSynchronizationManager.registerSynchronization( new ConnectionSynchronization(holderToUse, dataSource)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { TransactionSynchronizationManager.bindResource(dataSource, holderToUse); } } return con; }
DataSourceUtils 管理参与事务性的JDBC连接
猜你喜欢
转载自tmmh.iteye.com/blog/1840244
今日推荐
周排行