编程式事务:
@SpringBootApplication
@Slf4j
public class ProgrammaticTransactionDemoApplication implements CommandLineRunner {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
public static void main(String[] args) {
SpringApplication.run(ProgrammaticTransactionDemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
log.info("COUNT BEFORE TRANSACTION: {}", getCount());
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
jdbcTemplate.execute("INSERT INTO FOO (ID, BAR) VALUES (1, 'aaa')");
log.info("COUNT IN TRANSACTION: {}", getCount());
transactionStatus.setRollbackOnly();
}
});
log.info("COUNT AFTER TRANSACTION: {}", getCount());
}
private long getCount() {
return (long) jdbcTemplate.queryForList("SELECT COUNT(*) AS CNT FROM FOO")
.get(0).get("CNT");
}
}
声明式事务:
使用@Transactional注解
理解:spring的事务通过aop实现,在同级方法调用时,会发生失效的现象。因为这时候,原因是同级方法调用会直接执行方法,不会经过代理,aop的增强方法不会起效。如果要避免这种情况,需要把自己注入,然后通过类名调用即可。
注意的坑:
1.加在private方法,无效
2.加在未加入接口的public方法,再通过普通接口方法调用,无效
3.加于接口方法,无论下面调用的是private或public都,有效
4.加于接口方法后,被本类普通接口方法直接调用,无效
5.加于接口方法后,被本类普通接口方法通过接口调用,有效
6.加于接口方法后,被它类的接口方法调用,有效
7.驾驭接口方法后,被它类的私有方法调用,有效
总结:Transactional是否生效,仅取决于是否加载于接口方法,并且是否通过接口方法调用(而不是本类调用)
注:以上内容非本人原创,转载于jimin知识星球。