gpt4 book ai didi

java - 在@Transactional 服务方法中捕获 DataIntegrityViolationException

转载 作者:行者123 更新时间:2023-12-01 11:18:16 36 4
gpt4 key购买 nike

我有一个带有 Hibernate 的 REST Spring 启动应用程序。为简单起见,我们假设此工作流程:

  • Controller 处理传入请求,调用服务方法
  • 服务方式为@Transactional , 做一些业务逻辑并调用 Persistence 方法
  • 持久性方法由 DAO 对象处理,将内容保存到数据库中。

  • 数据库有一个 uniqueusername 的约束用户的。我现在的工作方式是这样的:
  • 客户端向 Controller 发送请求
  • Controller 调用服务
  • 服务尝试通过 DAO 保存对象。如 DataViolationException发生,服务返回自定义异常
  • Controller 捕获自定义异常并发回适当的响应


  • 伪代码是这样的:
    public class UserController {
    @RequestMapping("/user")
    public User createUser(...){
    try{
    return userService.createUser(...);
    } catch (UserAlreadyExistsException e){
    // Do some processing and return error message to client
    }
    }
    }

    public class UserService {
    @Transactional
    public User createUser(...){
    (...)
    try{
    userDAO.save(newUserObject);
    } catch(DataIntegrityViolationException e){
    throw new UserAlreadyExistsException(username);
    }
    }
    }

    但是,这样我在尝试创建重复用户时会收到错误消息。
    javax.persistence.RollbackException: Transaction marked as rollbackOnly

    解决此问题的一种方法 好像是让 DataIntegrityViolationException从事务中“冒泡”(而不是在服务中捕获它)。但这意味着 Controller 必须处理持久性异常,我不喜欢那样。

    我更喜欢服务抛出“可理解”的异常以供 Controller 处理。该服务知道预期什么持久性异常以及何时发生,并且能够“翻译”广泛的 DataIntegrityViolationException变成一个有意义的。

    有没有办法以这种方式处理异常?我不是特别喜欢使用“2 层服务层”来实现这一点的想法。

    编辑:我想抛出自定义异常的另一个原因是编译器需要捕获它。我想强制 Controller 处理所有可能发生的异常。

    最佳答案

    您的存储库需要扩展 JpaRepository,当您这样做时。您可以使用该存储库中的 saveAndFlush 方法。这意味着,您的代码将立即在数据库上执行,并在完成事务之前抛出异常,您将能够在 Catch 块中捕获它。我还添加了用于删除操作的示例。
    存储库:

    import org.springframework.data.jpa.repository.JpaRepository;

    public interface UserDAO extends JpaRepository<User, Long> {
    }
    服务:
     public class UserService {
    private UserDAO userDAO;

    (...)

    @Transactional
    public User createUser(...){
    (...)
    try{
    userDAO.saveAndFlush(newUserObject);
    } catch(DataIntegrityViolationException e){
    throw new UserAlreadyExistsException(username);
    }
    }

    @Transactional
    public void deleteUser(...){
    (...)
    try{
    userDAO.delete(deletingUserObject);
    userDAO.flush();
    } catch(DataIntegrityViolationException e){
    throw new UserException(username);
    }
    }
    }

    关于java - 在@Transactional 服务方法中捕获 DataIntegrityViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36498327/

    36 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com