TransactionTemplate的灵活性好,可以给代码块加事务处理,而不是方法粒度的控制。
FruitShop实现:
public class TxTemplateJdbcFruitShop extends JdbcDaoSupport implements FruitShop {
private PlatformTransactionManager txManager;
public void setTxManager(PlatformTransactionManager txManager) {
this.txManager = txManager;
}
@Override
public boolean purchase(final int fruitId, final String userName, final int count) {
TransactionTemplate txTemplate = new TransactionTemplate(txManager);
final String querySql = "SELECT PRICE FROM FRUIT WHERE ID = ?";
final String upStockSql = "UPDATE FRUIT_STOCK SET STOCK = STOCK - ? WHERE ID = ?";
final String upAccountSql = "UPDATE ACCOUNT SET BALANCE = BALANCE - ? WHERE USERNAME = ?";
int retVal = txTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
int price = getJdbcTemplate().queryForInt(querySql, new Object[] { fruitId });
getJdbcTemplate().update(upStockSql, new Object[] { count, fruitId });
getJdbcTemplate().update(upAccountSql, new Object[] { price * count, userName });
return 1;
}
});
return retVal == 1;
}
}
beans-fruitshop.xml文件加入:
<bean id="txTemplateFruitShop" class="com.john.tx.service.impl.TxTemplateJdbcFruitShop">
<property name="dataSource" ref="dataSource" />
<property name="txManager" ref="txManager" />
</bean>
JdbcFruitShopTest类加入:
@Resource(name = "txTemplateFruitShop")
FruitShop txTemplateFruitShop;
@Test
public void txTemplateTest() {
int fruitId = 1;
String userName = "user1";
int count = 3;
txTemplateFruitShop.purchase(fruitId, userName, count);
}
附:
1. 可以直接注入TransactionTemplate实例,不用在代码中实例化:
去除PlatformTransactionManager属性,直接使用TransactionTemplate属性:
private TransactionTemplate txTemplate;
public void setTxTemplate(TransactionTemplate txTemplate) {
this.txTemplate = txTemplate;
}
beans-fruitshop.xml加入:
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager" />
</bean>
<bean id="txTemplateFruitShop" class="com.john.tx.service.impl.TxTemplateJdbcFruitShop">
<property name="dataSource" ref="dataSource" />
<property name="txTemplate" ref="txTemplate" />
</bean>
2. execute方法可以接受TransactionCallback接口的抽象类,如TransactionCallbackWithoutResult:
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
...
}
});
看下其实现:
接口方法中抽出一个没有返回结果的抽象方法(由用户自己实现),返回null是为了适配接口。
public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {
public final Object doInTransaction(TransactionStatus status) {
doInTransactionWithoutResult(status);
return null; // 返回null
}
// 抽象方法,需要自定义实现
protected abstract void doInTransactionWithoutResult(TransactionStatus status);
}