@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
String[] label() default {};
/*事务传播行为*/
Propagation propagation() default Propagation.REQUIRED;
/*事务隔离级别*/
Isolation isolation() default Isolation.DEFAULT;
/*超时时间*/
int timeout() default -1;
String timeoutString() default "";
/*是否只读*/
boolean readOnly() default false;
/*回滚*/
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
/*不回滚*/
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
结合数据库事务实现来看,其中比较陌生的概念应该是事务传播行为,这个概念出现的原因是Spring声明式事务处理事务的单元是方法级别,
这个Spring声明式事务的源码实现过程中也可以体会到,不管你是将@Transactional放到类之上还是方法之上,最终都会在方法执行之前进行拦截并在方法执行全过程中执行创建事务、回滚事务、提交事务。当执行到一个新的方法,又会重新执行这些逻辑。
也就是说一般执行一个方法就可以开一个事务,这和数据库事务有些差别,数据库事务可以在一个事务中执行多个方法,所以Spring执行多个方法的过程就会考虑是共用一个事务还是重新使用新的事务。
这属于对数据库事务的Java实现,对并发的考虑
事务需要在一定时间内进行提交,如果没提交进行回滚
默认值为-1,设置时间以秒为单位进行计算。
是否只读
读:查询操作,写:添加修改删除操作
readOnly默认值false,表示可以查询,可以添加修改删除。
设置readOnly值为true,只能查询操作
在Java代码中实现事务,这和数据库sql语句中实现事务有所不同,它会将Java的异常机制耦合到数据库事务中,这个是sql处理事务时没有遇到过的场景,也是我们之后回滚失效的原因。
(1)设置查询哪些异常进行事务回滚
(2)设置出现哪些异常不进行事务回滚