最近遇到事务的处理,嵌套事务,自己研究,整理一下。
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 {
}
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();
}
}
}
执行结果:都插入成功。
结论:不同事务,只要对异常进行捕获并处理,都会执行成功