Spring提供了声明式事务,为了对事务的精细控制,spring提供了事务的传播属性。
PROPAGATION_REQUIRED
这是默认的传播属性值,如果当前已经存在事务,那么加入该事务,如果不存在事务,创建一个事务。
@Transactional
public void service(){
serviceA();
serviceB();
}
@Transactional
serviceA();
@Transactional
serviceB();
serviceA和serviceB都声明了事务,默认情况下,propagation=PROPAGATION_REQUIRED,整个service调用过程中,只存在一个共享的事务,当有任何异常发生的时候,所有操作回滚。
PROPAGATIOIN_SUPPORTS
如果当前已经存在事务,那么加入该事务,否则创建一个所谓的空事务(可以认为无事务执行)。
public void service(){
serviceA();
throw new RunTimeException();
}
@Transactional(propagation=Propagation.SUPPORTS)
serviceA();
serviceA执行时当前没有事务,所以service中抛出的异常不会导致serviceA回滚。
PROPAGATION_MANDATORY
当前必须存在一个事务,否则抛出异常。
public void service(){
serviceB();
serviceA();
}
serviceB(){
do sql
}
@Transactional(propagation=Propagation.MANDATORY)
serviceA(){
do sql
}
这种情况执行service会抛出异常,如果defaultAutoCommit=true,则serviceB是不会回滚的,defaultAutoCommit=false,则serviceB执行无效。
PROPAGATION_REQUIRES_NEW
暂停当前事务(当前无事务则不需要),创建一个新事务。两个事务没有依赖关系,可以实现新事务回滚,但外部事务继续执行。
@Transactional
public void service(){
serviceB();
try{
serviceA();
}catch(Exception e){
}
}
serviceB(){
do sql
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
serviceA(){
do sql 1
1/0;
do sql 2
}
当调用service接口时,由于serviceA使用的是REQUIRES_NEW,它会创建一个新的事务,但由于serviceA抛出了运行时异常,所以serviceB是正常提交的。
Propagation.NOT_SUPPORTED
如果当前存在事务,挂起当前事务,然后新的方法在没有事务的环境中执行,没有spring事务的环境下,sql的提交完全依赖于defaultAutoCommit属性值 。
@Transactional
public void service(){
serviceB();
serviceA();
}
serviceB(){
do sql
}
@Transactional(propagation=Propagation.NOT_SUPPORTED)
serviceA(){
do sql 1
1/0;
do sql 2
}
PROPAGATION_NEVER
如果当前存在事务,则抛出异常,否则在无事务的环境上执行代码。
public void service(){
serviceB();
serviceA();
}
serviceB(){
do sql
}
@Transactional(propagation=Propagation.NEVER)
serviceA(){
do sql 1
1/0;
do sql 2
}
PROPAGATION_NESTED
如果当前存在事务,则使用SavePoint技术把当前事务状态进行保存,然后底层共用一个连接,当NESTED内部出错的时候,自动回滚到SavePoint这个状态,只要外部捕获到异常,就可以继续进行外部的事务提交,而不受到内嵌业务的干扰,但是,如果外部事物抛出异常,整个大事务都会回滚。
@Transactional
public void service(){
serviceA();
try{
serviceB();
}catch(Exception e){
}
}
serviceA(){
do sql
}
@Transactional(propagation=Propagation.NESTED)
serviceB(){
do sql1
1/0;
do sql2
}
serviceB是一个内嵌的业务,内部抛出的运行时异常,所以serviceB整个被回滚,由于service捕获异常,所以serviceA是可以正常提交的。
最后欢迎大家访问我的个人网站:1024s