package io.inverseli.service;
import io.inverseli.base.domain.Person;
import io.inverseli.base.domain.Product;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
public class CommonService {
@Resource
private ProductService productService;
@Resource
private PersonService personService;
public void test() {
Product product = new Product("002", "iphone", "the phone product");
productService.save(product);
// 不加Transactional,product正常插入数据库,抛出异常后下边不执行,person数据未插入
// 加Transactional,抛出异常后,事务回滚,都未插入成功
int i = 1 / 0;
Person person = new Person("002", "jack", 18);
personService.save(person);
}
}
复现 Transaction rolled back because it has been marked as rollback-only 错误
package io.inverseli.service;
import io.inverseli.base.domain.Person;
import io.inverseli.base.domain.Product;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
@Transactional(rollbackFor = Exception.class)
public class CommonService {
@Resource
private ProductService productService;
@Resource
private PersonService personService;
public void test() {
Product product = new Product("002", "iphone", "the phone product");
try {
productService.save(product);
} catch (Exception e) {
e.printStackTrace();
}
Person person = new Person("002", "jack", 18);
System.out.println("insert person");
personService.save(person);
}
}
package io.inverseli.service;
import io.inverseli.base.domain.Product;
import io.inverseli.base.mapper.ProductMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
@Service
@Transactional(rollbackFor = Exception.class)
// @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public class ProductService {
@Resource
private ProductMapper productMapper;
public void save(Product product) {
productMapper.insert(product);
int i = 1 / 0;
}
}
productService 的 save 方法会抛出一个异常并且没有被捕获,CommonService 在掉用 productService 的 save 时,捕获了可能发生的异常,导致程序可以继续往下执行。
productService 声明了事务,抛出错误后要进行回滚,而事务的传播行为采用的是默认的 REQUIRED,已经存在事务就加入,不会创建新的事务,所以 ProductService 和 CommonService 采用同一个事务,而此时 CommonService 要把事务进行提交,ProductService 要把事务进行回滚,就产生了 Transaction rolled back because it has been marked as rollback-only 的问题。