Spring的事务

125 阅读1分钟

编程式事务:

@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知识星球。