还是采用经典案例 银行转账 来构建代码,假设张三和李四账户都有1000元,现在张三向李四转账200元,观察spring是怎么管理事务的。
一、代码示例
① dao类:
/**
* 创建人:taofut
* 创建时间:2019-01-08 19:31
* 描述:
*/
public interface AccountDao {
/**
* @param out 转出账号
* @param money 转账金额
*/
public void outMoney(String out,Double money);
/**
* @param in 转入账号
* @param money 转账金额
*/
public void inMoney(String in,Double money);
}
② dao实现类:
/**
* 创建人:taofut
* 创建时间:2019-01-08 19:33
* 描述:
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
/**
* @param out 转出账号
* @param money 转账金额
*/
public void outMoney(String out, Double money) {
String sql="update account set money = money - ? where name = ?";
this.getJdbcTemplate().update(sql,money,out);
}
/**
* @param in 转入账号
* @param money 转账金额
*/
public void inMoney(String in, Double money) {
String sql="update account set money = money + ? where name = ?";
this.getJdbcTemplate().update(sql,money,in);
}
}
③ service类:
/**
* 创建人:taofut
* 创建时间:2019-01-08 19:26
* 描述:转账业务接口
*/
public interface AccountService {
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transfer(String out,String in,Double money);
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transferException(String out,String in,Double money);
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transferTransaction(String out, String in, Double money);
}
④ service实现类:
/**
* 创建人:taofut
* 创建时间:2019-01-08 19:29
* 描述:
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
/**注入事务管理的模板*/
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transfer(String out, String in, Double money) {
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transferException(String out, String in, Double money) {
accountDao.outMoney(out,money);
int i = 1 / 0;
accountDao.inMoney(in,money);
}
/**
* @param out 转出账号
* @param in 转入账号
* @param money 转账金额
*/
public void transferTransaction(final String out, final String in, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//在这里写事务相应的代码
accountDao.outMoney(out,money);
int i = 1 / 0;
accountDao.inMoney(in,money);
}
});
}
}
⑤ 配置文件applicationContext.xml:
二、spring事务所需条件
① 资源文件里面得配置事务管理器和事务管理模板,事务配置模板引用事务管理器,然后service类再引用事务管理模板。
② service类哪个方法需要加事务,就将该方法里的内容写入到如下代码里面:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//在这里写事务相应的代码
...
}
});
三、代码测试结果
import com.ft.demo1.AccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
/**
* 创建人:taofut
* 创建时间:2019-01-08 20:29
* 描述:转账案例测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest1 {
@Resource(name = "accountService")
private AccountService accountService;
@Test
public void demo1(){
accountService.transferTransaction("zhangsan","lisi",200d);
System.out.println("转账完成...");
}
}
没加事务:
public void transferTransaction(final String out, final String in, final Double money) {
accountDao.outMoney(out,money);
int i = 1 / 0;
accountDao.inMoney(in,money);
}
张三给李四转了200元,然后出现异常,没回滚。李四增加200元的操作没进行下去,最终导致张三转了200元,李四没收到钱。200元就这么消失了,这显然是不合理的。
加了事务:
public void transferTransaction(final String out, final String in, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//在这里写事务相应的代码
accountDao.outMoney(out,money);
int i = 1 / 0;
accountDao.inMoney(in,money);
}
});
}
张三给李四转了200元,然后出现异常,回滚了。最终张三200元没转出去,李四也没收到钱。
四、总结
编程式事务,从字面意思就能理解它是需要我们手动编写代码的,从“spring事务所需条件”我们知道,如果要给很多个service里的很多方法添加事务,那么资源文件里得配置很多service,并且每个service都得引用事务管理模板,每个方法里的内容也都要被事务配置模板方法给包裹进来,这样的做法耦合度太高,开发工作量也比较大,所以实际生活中用的很少。