Spring编程式事务详解,java常用技术框架

def.setName(“SomeTxName”);

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);

try {

// 执行业务逻辑

}

catch (MyException ex) {

txManager.rollback(status);

throw ex;

}

txManager.commit(status);

2 TransactionTemplate

====================================================================================

PlatformTransactionManager中部分代码是可以重用的,所以spring对其进行了优化,采用模板方法模式就其进行封装,主要省去了提交或者回滚事务的代码。

若你选择编程式事务管理,Spring推荐使用 TransactionTemplate。 类似使用JTA的 UserTransaction API (除了异常处理的部分稍微简单点)。

2.1 简介


TransactionTemplate 采用与Spring中别的模板同样的方法,如 JdbcTemplate 。

使用回调机制,将应用代码从样板式的资源获取和释放代码中解放。

同一个事务管理的代码调用逻辑中,每次执行 SQL,都是基于同一连接,所有连接都是从一个公共地方TransactionSynchronizationManager获取。

所以获取连接操作不应该在 ORM 层框架,而是由 Spring 维护。

JdbcTemplate源码

@Override

@Nullable

public T execute(ConnectionCallback action) throws DataAccessException {

Assert.notNull(action, “Callback object must not be null”);

Connection con = DataSourceUtils.getConnection(obtainDataSource());

try {

// Create close-suppressing Connection proxy, also preparing returned Statements.

Connection conToUse = createConnectionProxy(con);

return action.doInConnection(conToUse);

}

catch (SQLException ex) {

// Release Connection early, to avoid potential connection pool deadlock

// in the case when the exception translator hasn’t been initialized yet.

String sql = getSql(action);

DataSourceUtils.releaseConnection(con, getDataSource());

con = null;

throw translateException(“ConnectionCallback”, sql, ex);

}

finally {

DataSourceUtils.releaseConnection(con, getDataSource());

}

}

从给定的数据源获取连接。 知道绑定到当前线程的相应连接,例如在使用DataSourceTransactionManager 。 如果事务同步处于活动状态,例如在JTA事务中运行时,则将连接绑定到线程。

mybatis 中的各种 Mapper,其实底层就是通过使用 sqlSession 执行的。

而不管是 jdbcTemplate 还是 mybatis,获取连接都是通过 Spring的TransactionSynchronizationManager:

为何使用ThreadLocal存储资源?

若一个线程请求事务处理过程还在正常进行,但同时另一个线程并发也请求了同一事务的处理方法而且出现了异常要回滚了,若两个线程共用同一个数据库连接,就会导致回滚时影响原来正常执行的线程!所以连接对象是使用 ThreadLocal 存储

的。就是为了避免多线程共用同一个连接,导致回滚时出现数据错乱。

使用 TransactionTemplate 会增加你的代码与Spring的事务框架和API间的耦合。所以是否使用编程式事务管理由你自己决定。

应用代码必须在一个事务性的上下文中执行,这样就会像这样一样显式的使用TransactionTemplate。作为应用程序员, 会写一个 TransactionCallback 的实现, (通常会用匿名类实现 )这样的实现会包含所以你需要在该事务上下文中执行的代码。

然后你会把一个你自己实现TransactionCallback的实例传递给TransactionTemplate暴露的execute 方法。

public class SimpleService implements Service {

// single TransactionTemplate shared amongst all methods in this instance

private final TransactionTemplate transactionTemplate;

// use constructor-injection to supply the PlatformTransactionManager

public SimpleService(PlatformTransactionManager transactionManager) {

Assert.notNull(transactionManager, “The ‘transactionManager’ argument must not be null.”);

this.transactionTemplate = new TransactionTemplate(transactionManager);

}

public Object someServiceMethod() {

return transactionTemplate.execute(new TransactionCallback() {

// the code in this method executes in a transactional context

public Object doInTransaction(TransactionStatus status) {

updateOperation1();

return resultOfUpdateOperation2();

}

});

}

}

如果不需要返回值,更方便的是创建一个 TransactionCallbackWithoutResult 匿名类

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

@Override

protected void doInTransactionWithoutResult(TransactionStatus status) {

updateOperation1();

updateOperation2();

}

});

回调方法内的代码可以通过调用 TransactionStatus 对象的 setRollbackOnly() 方法来回滚事务。

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {

try {

updateOperation1();

updateOperation2();

} catch (SomeBusinessExeption ex) {

status.setRollbackOnly();

}

}

});

2.2 指定事务设置


诸如传播模式、隔离等级、超时等等的事务设置都可以在TransactionTemplate中或者通过配置或者编程式地实现。

TransactionTemplate实例默认继承了默认事务设置。 下面有个编程式的为一个特定的TransactionTemplate定制事务设置的例子。

public class SimpleService implements Service {

private final TransactionTemplate transactionTemplate;

public SimpleService(PlatformTransactionManager transactionManager) {

猜你喜欢

转载自blog.csdn.net/m0_54850604/article/details/122236379