Java事务以及嵌套事务

2019-09-29  本文已影响0人  程序员Anthony

最近遇到事务的处理,嵌套事务,自己研究,整理一下。

1 先看结论

1、在Java事务中,事务的嵌套,如果有事务成功,那么则都成功,否则都不会成功。
2、如果事务中存在异常,只要对异常进行捕获和处理,都为执行成功,否则都不会执行成功。

2 Propagation取值

REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;

SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行;

MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException;

REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;

NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起;

NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。

3 预设场景

这里直接测试spring boot 使用spring data jpa添加一个用户进行测试

实体类user

@Data
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long id;

    private String userName;

    public User(String userName) {
        this.userName = userName;
    }
}

UserRepository类

@Repository
public interface UserRepository extends CrudRepository<User,Long> {
}

UserService类

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;
}

4 实际场景使用

4.1 场景:并性事务

并行事务:
A:方法事务为默认的REQUIRED
B:方法事务为 REQUIRES_NEW 或者 REQUIRED


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void test1() {
        userService.addUser1(new User("user1"));
        userService.addUser2(new User("user2"));
    }
}

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;

    @Transactional(rollbackFor = Exception.class)
    public void addUser1(User user) {
        userRepository.save(user);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addUser2(User user) {
        userRepository.save(user);
        throw new RuntimeException();
    }

}

执行结果:
保存了user1.

结论:并行事务不存在事务影响

4.2 场景:嵌套相同事务

a) 事务嵌套,在同一个事务中,没有对异常进行处理


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void test2() {
        userService.addUser3();
    }

}

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;


    @Transactional(rollbackFor = Exception.class)
    public void addUser3() {
        userRepository.save(new User("user3"));
        this.addUser4(new User("user4"));

    }

    @Transactional(rollbackFor = Exception.class)
    public void addUser4(User user) {
        userRepository.save(user);
        throw new RuntimeException();
    }

}

执行结果:两个都没有插入成功

结论:由于两个都是在一个事务当中,所以只要有一个方法事务有问题,那么都不会插入成功。

b) 事务嵌套,在同一个事务中,对异常进行处理


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void test3() {
        userService.addUser5();
    }


}

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;


    @Transactional(rollbackFor = Exception.class)
    public void addUser5() {
        userRepository.save(new User("user5"));
        this.addUser6(new User("user6"));
    }

    @Transactional(rollbackFor = Exception.class)
    public void addUser6(User user) {
        userRepository.save(user);
        try {
            throw new RuntimeException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:两个都插入成功。
 结论:如果事务存在异常,并进行捕获处理,不会影响事务。

4.3 场景:嵌套不同事务

a)事务嵌套,在不同事务中,没有对异常进行处理


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void test4() {
        userService.addUser7();
    }

}

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;


    @Transactional(rollbackFor = Exception.class)
    public void addUser7() {
        userRepository.save(new User("user7"));
        this.addUser8(new User("user8"));
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addUser8(User user) {
        userRepository.save(user);
      throw new RuntimeException();
    }
}

执行结果:都没有插入成功。
 结论:不同事务中,嵌套的事务,没有对异常进行处理,都不会执行成功。(其实在外部事务中出错,两个也是都不会插入成功数据。)

b)事务嵌套,在不同事务中,对异常进行处理


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    public void test5() {
        userService.addUser9();
    }

}

@Service
public class UserService {
    @Autowired
    UserRepository userRepository;



    @Transactional(rollbackFor = Exception.class)
    public void addUser9() {
        userRepository.save(new User("user9"));
        this.addUser10(new User("user10"));
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void addUser10(User user) {
        userRepository.save(user);
        try {
            throw new RuntimeException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行结果:都插入成功。
 结论:不同事务,只要对异常进行捕获并处理,都会执行成功

上一篇下一篇

猜你喜欢

热点阅读