当我们在Spring中进行事务操作(e.g., 向数据表添加数据时), 如果程序在执行中出现
异常
,我们一定希望进行/了解本次基于的事务数据库操作是否会回滚(Rollback),那么我们就以一定的现实操作为例查看说明事物操作时如果出现异常时事物是否会进行回滚。
实体类是一个简单的User表,其中ID为自增长
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class User10 {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
}
Repository是一个基于BaseRepository(JPARpository)的拓展类
@Repository
public interface UserRepository10 extends BaseRepository<User10,Integer> {
}
Service类只有一个添加用户方法,开启事物(@Transactional
)
@Service
@Transactional
public class UserService10 {
@Autowired
private UserRepository10 userRepository10;
public void addUser(User10 user){
userRepository10.save(user);
}
}
在正常情况下我们通过下列实验代码向数据库添加名为Alice的用户
@Test
public void addUserTest() {
User10 user = new User10();
user.setName("Alice");
userService10.addUser(user);
}
在出现受检异常(我们这里以IO异常为例)并进行捕获的情形下我们通过下列实验代码向数据库添加名为Bob的用户,Service修改后的代码如下:
public void addUser(User10 user) {
userRepository10.save(user);
try {
Files.readString(Path.of("A:/not_exist.a"));
}
catch (IOException e) {
e.printStackTrace();
}
}
测试代如下:
@Test
public void addUserTest() {
User10 user = new User10();
user.setName("Bob");
userService10.addUser(user);
}
在出现受检异常(我们这里以算术异常为例)但直接抛出的情形下我们通过下列实验代码向数据库添加名为Cayce的用户,Service修改后的代码如下:
public void addUser(User10 user) throws IOException {
userRepository10.save(user);
Files.readString(Path.of("A:/not_exist.a"));
}
测试代码如下:
public void addUserTest() throws IOException {
User10 user = new User10();
user.setName("Cayce");
userService10.addUser(user);
}
这里程序仍然报错。我们继续观察事物继续回滚:
可以发现事物仍然正常进行,没有回滚。因此我们可以得出结论,当事物进行中出现受检异常
时,事物不会回滚。
在这里我们直接抛出RuntimeException
进行加入名为David用户的测试。
Service修改后的代码如下:
public void addUser(User10 user) {
userRepository10.save(user);
throw new RuntimeException();
}
因为非受检异常不需要显式捕获,我们的测试代码如下:
public void addUserTest() {
User10 user = new User10();
user.setName("David");
userService10.addUser(user);
}
这里测试继续报错:
我们继续观察事务是否回滚:
可以发现,事务回滚了。
因此我们发现:当事物进行中出现非受检异常
时,事务回滚。
此外还有一个有趣的事情,我们以正常方式加入David后,观察Id值:
我们可以发现刚才因为回滚而产生的id=4的对象被跳过了
至此我们可以得出结论:
受检异常
时,事务不会回滚,当事务中出现非受检异常
时,事务回滚非受检异常
进行事务回滚操作