spring事务是基于jdbc实现的;
spring提供2种开启事务方式,一种是编程式,一种是注解方式@Transactional
只需要在某个方法上加上@Transactional注解即可;添加了@Transactional注解时,spring会把事务的自动提交设为false,当业务逻辑方法出错时就会回滚;
可以在@Transactional注解的rollbaackFor属性中配置 出现哪些异常 才会回滚,默认会对RuntimeExecption和Error进行回滚(前提是这个异常不能捕获catch);
@Transactional(rollbackFor = Exception.class)
事务隔离级别
mysql默认的事务隔离级别时rc,spring事务默认是rr;
如果数据库和spring都配置了事务隔离机制,那么最终以spring为准;
如果spring配置的事务隔离机制数据库不支持,那么以具体的数据库为准;
事务的传播机制
https://blog.csdn.net/yuanlaishini2010/article/details/45792069
ServiceA {
void methodA() {
ServiceB.methodB();
// int i=1/0;
}
}
ServiceB {
void methodB() {
do samething
}
}
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED(默认):支持当前事务,如果当前没有事务(不在另一个事务里),就新建一个事务。
如果a方法没有事务,b有事务,a方法出现异常(不是b方法里出现的异常),不会回滚;
如果a、b方法都有事务,a调用b方法,b就不会起事务(即,b支持当前a的事务),a、b无论哪个发生异常,都将回滚;
PROPAGATION_SUPPORTS
PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务(不在另一个事务中),就以非事务方式执行。
a方法没有事务,b方法有事务,a调用b,则b也不用事务(都以非事务运行);
如果a、b方法都有事务,a调用b方法,b就不会起事务(即b,支持当前a的事务),a、b无论哪个发生异常,都将回滚;
PROPAGATION_MANDATORY
PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
如果a、b方法都有事务,a调用b方法,b就不会起事务(即,b支持当前a的事务),a、b无论哪个发生异常,都将回滚;
如果a方法没有事务,b方法有事务,a调用b则抛异常;
PROPAGATION_REQUIRES_NEW
PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
如果a、b都有事务,a调用b时,a的事务先被挂起 并为b新建一个事务,等到b的事务完成后,a事务继续执行,即a和b各自运行各自的事务;
注意,如果a出现异常,b的事务已提交(b没有异常),a会回滚,b不会回滚;
PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
不能在事务中运行。如果a的事务级别是PROPAGATION_REQUIRED, 而b的事务级别是PROPAGATION_NEVER ,那么b就要抛出异常了。
PROPAGATION_NESTED
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.
事务失效
https://www.cnblogs.com/shijianchuzhenzhi/p/13237571.html
类没有被Spring管理
// @Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
// do samething
}
}
把@Service 注解注释掉,这个类就不会被 Spring 管理了。
方法不是 public的 – 该异常一般情况都会被编译器识别
自身this调用
@Service
public class OrderServiceImpl implements OrderService {
public void a() {
b(); //this.b();自身调用,没有走spring的代理类;
}
@Transactional
public void b() {
// do samething;
}
}
a方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的b 方法,发生异常时,b方法的事务不生效,不会回滚;
因为,spring的事务实现是使用了代理类来实现,这里其实是this.b();
在a方法上也添加事务,可以使事务生效;
或者,使用让spring的代理类
@Service
public class TestService {
@Autowired
private TestService testService;
/**
* 这里调用methodB() 的事务将会生效
*/
public void methodA(){
testService.methodB(); //testService是spring代理的;
}
@Transactional
public void methodB(){
}
异常被捕获
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void a(Order order) {
try {
// update order;
}catch (Exception e){
//do something;
}
}
}
出现异常时,异常被catch到,导致a方法的事务不生效,不会回滚;
解决方法,catch到后,再通过throw抛出异常;
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void a(Order order) {
try {
// update order;
}catch (Exception e){
//do something;
throw e;
}
}
}
抛出异常类型不对
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
try {
} catch {
throw new Exception("更新错误");
}
}
}
这样事务也是不生效的,因为默认回滚的是:RuntimeException。
如果想触发其他异常的回滚,需要在注解上配置一下,
如:@Transactional(rollbackFor = Exception.class)
传播类型不支持事务
数据库本身不支持事务
例如MyIASM引擎;