声明式事务:@Transactionl 运行时间过长 导致长事务(大事务)
可采用 编程式事务:
编程式事务需要自己通过编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager来实现事务;Spring更推崇使用TransactionTemplate来实现编程式事务;
public Base login(String name) {
TransactionDefinition definition = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(definition);
try {
baseDao.login(name);
Base base = baseDao.login(name);
base.setName("updateName");
baseDaoImpl.update(base);
txManager.commit(status);
return base;
}catch (Exception e) {
e.printStackTrace();
txManager.rollback(status);
}
return null;
}
执行流程:
A:
PlatformTransactionManager调用getTransaction(definition),是由其实现类AbstractPlatformTransactionManager来获取连接,由AbstractPlatformTransactionManager中的getTransaction(definition)来获取连接;在getTransaction(definition)中调用了该类的doBegin(transaction, definition)来获取连接,该方法是由式实现类DataSourceTransactionManager的doBegin(transaction, definition)来获取连接;在该方法中调用了this.dataSource.getConnection()生成一个连接对象;调用了txObject.setConnectionHolder(new ConnectionHolder(newCon), true)将连接放入ConnectionHolder;调用了txObject.getConnectionHolder().getConnection()来获取连接对象;调用了con.setAutoCommit(false)开启事务;调用了txObject.getConnectionHolder().setTransactionActive(true)设置当前连接对象激活状态;调用了TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder())绑定连接到当前线程;bindResource(Object key, Object value)调用了resources.get()获取Map连接对象,调用了map.put(actualKey, value)获取连接对象。
B.
jdbcTemplate.update(final String sql),该方法中调用了该类的execute(new UpdateStatementCallback())来执行的;该方法中调用了DataSourceUtils.getConnection(getDataSource())来获取ConnectionHolder;该方法中调用了该类的doGetConnection(dataSource)来完成的,该方法中调用了(ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource)来完成的,该方法中调用了doGetResource(actualKey)来完成的,在该方法中调用了resources.get()获取当前Map对象,调用了map.get(actualKey)来获取ConnectionHolder,DataSourceUtils中的doGetConnection(DataSource dataSource)方法中调用了conHolder.getConnection()来获取连接对象。jdbcTemplate的execute(StatementCallback<T> action)方法中调用了action.doInStatement(stmtToUse)来执行Statement。
C.
PlatformTransactionManager.commit(status),是由其实现类AbstractPlatformTransactionManager.commit(status)来提交事务的,该方法中调用了该类的processCommit(defStatus)方法来完成的,processCommit方法中调用了该类的doCommit(status)方法来完成的,doCommit(status)又是由其实现DataSourceTransactionManager来完成的,该方法中调用了txObject.getConnectionHolder().getConnection()来获取连接对象,调用了con.commit()来提交事务的。
开启事务:AbstractPlatformTransactionManager.getTransaction().dobegin().dataSource.getConnection().setConnectionHolder()——>getConnectionHolder.getConnection() ——>con.setAutoCommit(false)——>(绑定连接到线程)TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder())
绑定连接到线程:TransactionSynchronizationManager.bindResource().map.put(actualKey, value)
获取连接对象:JdbcTemplate.update()——>JdbcTemplate.execute()——>JdbcTemplate.execute().DataSourceUtils.getConnection(getDataSource())——>DataSourceUtils.getConnection().doGetConnection
——>(ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource).doGetResource(actualKey).resources.get().get(actualKey)——>DataSourceUtils.conHolder.getConnection()
提交事务:AbstractPlatformTransactionManager.commit().processCommit().doCommit()——>DataSourceTransactionManager.doCommit().txObject.getConnectionHolder().getConnection().commit()