【问题标题】:unable to catch hibernate exception caused by constraints violation无法捕获因违反约束而导致的休眠异常
【发布时间】:2018-03-26 17:14:32
【问题描述】:

我查看了许多其他关于不捕获异常的问题(包括Can't catch ConstraintViolationException),但没有一个问题与我相同。

使用 RestEasy 联网并使用 Hibernate 链接 Postgres db。

我有一个对象:

@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"user_id"})})
public class Outcome {

    @Id
    @GeneratedValue
    private Long id;

    @OneToOne
    private User user;

    private String anotherAttribute;
}

db 服务通过 OutcomeResource.saveOutcome 发送一个 Outcome:

@POST
@Consumes("application/json")
@Transactional
public Response saveOutcome(Outcome outcome){
    try {
        myRepository.save(outcome);
        return Response.ok().build();
    } catch (Exception e) {
        System.out.println("I caught the exception:" + e);
        return Response.status(Response.Status.BAD_REQUEST).build();
    }
}

然后通过 OutcomeRepository.save 将其保存在数据库中:

public void save(Outcome outcome) {
    try {
        getEntityManager().persist(outcome);
    } catch (Exception e) {
        System.out.println("No I caught the exception : " + e);
    }
}

当第一个结果发布并为用户保存时,它成功保存在数据库中。如果发布第二个结果,则会按预期抛出错误。

缩短的错误堆栈跟踪是:

javax.persistence.RollbackException: 
   Error while committing the transaction
   Description: The server encountered an unexpected condition that
   prevented it from fulfilling the request.
   Exception: org.jboss.resteasy.spi.UnhandledException:
   javax.persistence.RollbackException: Error while committing the transaction
org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:78)...
Root cause: javax.persistence.RollbackException: 
    Error while committing the transaction...
Root cause: javax.persistence.PersistenceException:
    org.hibernate.exception.ConstraintViolationException: 
    could not execute statement...
Root cause: org.hibernate.exception.ConstraintViolationException: 
    could not execute statement...
Root cause: postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint
    Detail: Key (user_id)=(361) already exists.

我想捕获此错误以返回错误的请求响应。 尽管尝试在堆栈跟踪中捕获通用异常和每种特定类型的异常,但都没有输入任何 catch 块。

为什么这两种方法都没有捕获异常?怎么可能呢?

【问题讨论】:

  • 不是 EntityManager 抛出异常,而是事务。

标签: hibernate jpa exception


【解决方案1】:

后来我发现了几个小时的研究..

无法捕获异常,因为它是在方法完成后抛出的。这是因为服务层方法被标记为@Transactional,所以在该事务结束之前,hibernate 不会抛出异常。

如果使用 spring:编写一个转换异常的抛后建议显然可以让您处理这个问题,但是我没有对此进行测试。

我还没有找到在 Guice 中处理此异常的方法,因此将不处理它。在我的情况下这没问题。

良好的信息来源:http://forum.spring.io/forum/spring-projects/data/68995-transaction-manager-appears-to-be-eating-the-runtime-exception

【讨论】:

  • 或者另一种方式是,您可以将 @TransactionalOutComeResource.save.. 方法进一步向下移动到 repository and with that you should able to catch the exception in OutComeResponse.save...` 方法。
猜你喜欢
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
相关资源
最近更新 更多