JPA2 唯一约束:我真的需要刷新吗?

Pet*_*oye 5 java orm jpa unique-constraint jpa-2.0

我有一个 DAO,我需要在其中捕获唯一的约束异常。为此,唯一可行的解​​决方案是在持久化之后刷新我的 EntityManager。只有这样我才能进入一个catch块,我必须过滤掉异常。而且,我的 DAO 方法需要包含在一个事务中(REQUIRES_NEW),否则我会遇到 RollBackException。

难道我做错了什么?

try {
        em.persist(myObject);
        em.flush();
    } catch (PersistenceException ex) {
        if (ex.getCause() != null) {
            String cause = ex.getCause().toString();
            if (cause != null) {
                if (cause.contains("org.hibernate.exception.ConstraintViolationException")) {
                    logger
                            .error("org.hibernate.exception.ConstraintViolationException: possible unique constraint failure on name");
                    throw ex;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Pas*_*ent 4

难道我做错了什么?

EntityManager#persist()不会触发立即插入(除非您使用IDENTITY策略)。因此,如果您想实际将内存中的更改写入数据库并有机会捕获约束违规,则必须flush()“手动”(尽管这样做并不能严格保证任何内容,您的数据库可以配置为使用deferred限制)。

换句话说,在我看来,你正在做的事情是正确的。


我有一个带有 @Transactional 的服务方法(必需),称为 addNewObject()。在此方法中,发生的一些事情可能会引发异常(从而回滚事务)。这些调用之一是对 DAO 方法 addObject 的调用。由于唯一约束,此操作可能会失败。现在,如果我执行刷新,如果没有唯一违规,该对象将被持久化。但是,在服务中仍然可能存在其他原因导致该方法引发异常。

我认为你很困惑flush并且commit。如果外部出现问题addObject并抛出不可恢复的异常(但在同一事务内),则整个事务将被回滚,包括与调用INSERT相对应的语句persist()。综上所述,flush!= commit