【问题标题】:JPA2 unique constraint: do I really need to flush?JPA2 唯一约束:我真的需要刷新吗?
【发布时间】:2011-04-27 10:07:42
【问题描述】:

我有一个 DAO,我需要在其中捕获唯一约束异常。为此,唯一可行的解​​决方案是在持久化之后刷新我的 EntityManager。只有这样我才进入一个捕获块,我必须过滤掉异常。而且,我的 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;
                }
            }
        }
    }

【问题讨论】:

    标签: java orm jpa jpa-2.0 unique-constraint


    【解决方案1】:

    我是不是做错了什么?

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

    换句话说,你正在做的是 IMO 只是正确的方式。


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

    我认为您混淆了flushcommit。如果在addObject 之外出现问题并引发不可恢复的异常(但在同一事务内),则整个事务将回滚,包括与persist() 调用对应的INSERT 语句。综上所述,flush != commit

    【讨论】:

    • 刷新的问题是您的对象被持久化,因此任何需要完成的回滚(例如,调用 dao 的服务需要回滚)都没有实际意义。还是我在自欺欺人:-)
    • @Peter 您能否澄清您的问题,我不明白(您是否正在寻找一种解决方案来检查数据库约束违规而不接触数据库?)。还请添加有关交易问题的详细信息,这是我在最初的问题中没有理解的内容。
    • @Pascal:我有一个带有 @Transactional 的服务方法(必需),称为 addNewObject()。在这种方法中,会发生一些可能引发异常的事情(从而回滚事务)。其中一个调用是对 DAO 方法 addObject 的调用。由于唯一约束,这可能会失败。现在,如果我刷新,如果没有唯一的违规,该对象将被持久化。但是,在服务中可能还有其他东西会导致方法抛出异常。
    • 是的,它让我回顾了我的代码并清除了一些东西。现在一切正常。谢谢!
    猜你喜欢
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2018-12-22
    • 2017-01-10
    • 2011-04-07
    • 2013-10-06
    相关资源
    最近更新 更多