@Transactional避免存储库方法中的异常

@Transactional avoids exception in repository methods

提问人:tabool 提问时间:9/25/2023 最后编辑:Jenstabool 更新时间:9/25/2023 访问量:54

问:

我正在使用服务方法@Transactional

假设我们有这样的方法

@Transactional 
public void doWork() {
    User user = new User(1);
    user = userRepository.save(user);

    doOtherWorkIfAllIsOk(user);
}

private void doOtherWorkIfAllIsOk(User user) {
    System.out.println("Everything is alright");
    user.setName("Bob")
    userRepository.save(user);
}

例如,如果我没有为用户填写一些必填字段,该字段具有 ,则事务将捕获一个异常,该异常将抛出存储库方法,并且我的方法将通过调用该方法继续执行。nullable = falsedoOtherWorkIfAllIsOk()

如何配置事务行为,以便 Spring 在调用存储库方法时不会捕获异常。我需要的是,如果存储库方法中发生错误,则 doWork() 方法会抛出此异常并被中断,并且不应调用 doOtherWorkIfAllIsOk(User user) 方法,因为现在如果存储库方法中出现错误,则调用 doOtherWorkIfAllIsOk(User user) 方法。

java spring-data-jpa spring-transactions

评论

1赞 Jens 9/25/2023
注释仅用于生成表。它不用于验证@Column
0赞 Jens 9/25/2023
顺便说一句:您应该不要在数据库层上进行验证。在业务逻辑中执行此操作
0赞 Ken Chan 9/25/2023
我认为 repository.save() 如果无法将用户插入数据库,现在应该立即抛出异常。你到底想做什么?
0赞 tabool 9/26/2023
epository.save() 立即抛出异常,但@Transactional捕获此异常并返回继续执行我的方法,但它不应该继续执行。

答:

0赞 Hermann Steidel 9/25/2023 #1

我会考虑一种不同的方法。可以改进让数据库或持久性框架自动引发错误,然后捕获这些错误以控制代码流。有很多方法可以做到这一点,但我会考虑如下:

@Transactional 
public void doWork() {
    User user = new User(1);
    if (isUserValid(user)) {
       user = userRepository.save(user);
       doOtherWork(user);
    } else {
     //log.warn("user is invalid");
    }

   
}

private boolean isUserValid(User user) {
   //check user, return false if not valid
   // perhaps logging at debug level what's wrong is also helpful
}

这有几点:

  • 显式声明使用户无效的原因,可以独立于数据库或数据库框架进行测试。此外,你的代码现在的样子,其他人或你将来的样子,不会直观地知道是什么让用户有效。
  • 使用异常进行流控制通常是一个坏主意,也是一种反模式。异常应该是例外的,而不是正常业务逻辑的一部分
  • 既然你提到过,你可能想看看 Hibernate Validation 项目来使用基于注解的验证。如果你正在处理一个Spring Web项目,你可以很容易地启用它。但是,我还建议的一件事是,不要在接受表单字段的 Web 或表示层公开您的数据库类/实体。最好使用所谓的数据传输对象来为您处理验证。一旦有效,您就可以从中创建数据库对象以保存到数据库中。nullable = falseUser

例:

public class NewUserForm {

  @NotNull
  private String username;

}

//validation happens by the caller of this service layer method or before transforming here
public saveUser(NewUserForm userForm) {
    User user = transformToUser(userForm);
    userRepository.save(user);
    
}

有关在 Spring 中开始验证的更多信息,您可以 Google 搜索,您会找到大量关于此的“入门”指南。Spring Hibernate Validation