spring事务传播行为

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 的问题。

你可能感兴趣的:(spring事务传播行为)