Java 如何从JPA唯一约束冲突中获取值?

Java 如何从JPA唯一约束冲突中获取值?,java,jpa,jboss,ejb,unique,Java,Jpa,Jboss,Ejb,Unique,我正在用Primefaces做一个web项目,它从使用JPA的远程EJB发送和获取数据。在实体Bean中设置unique=true后,我得到了处理唯一值的代码: try{ emsave.persist(newItem); } catch (PersistenceException pe){ System.out.println("dupe found"); } 然后我回滚事务。 在Eclipse控制台中,我从Jboss获得以下消息: 09:15:12,179 WARN [or

我正在用Primefaces做一个web项目,它从使用JPA的远程EJB发送和获取数据。在实体Bean中设置
unique=true
后,我得到了处理唯一值的代码:

try{
    emsave.persist(newItem);
} catch (PersistenceException pe){
    System.out.println("dupe found");
}
然后我回滚事务。 在Eclipse控制台中,我从Jboss获得以下消息:

09:15:12,179 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-localhost-127.0.0.1-8189-6) SQL Error: 1062, SQLState: 23000
09:15:12,179 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-localhost-127.0.0.1-8189-6) Duplicate entry 'asdasd' for key 'username'

我必须将无法保存的对象发送回前端,并在表中显示它们,或者在表中以某种方式标记它们,以便用户知道他必须更改什么。我有办法做到这一点,但我不知道如何标记哪个字段的值不好。是否可能从该异常中获取“用户名”字段填写错误的信息,或者应该使用其他方法?我正在寻找最优雅的解决方案。

首先,
persist()
不会引发异常
persist()
仅通过将对象附加到持久性上下文将其标记为持久性。实际插入将在刷新时发生

第二,你似乎想在一个循环中这样做。所有运行时实例都是不可恢复的,并使上下文处于不可靠状态。一旦出现异常,应回滚当前事务,并且不应继续使用实体管理器


最后,这两个事实和常见的良好实践导致了解决方案:您不应该依赖异常来检测不正确的值。如果名称应该是唯一的,那么您应该发出一个查询来测试输入的名称是否已经存在于表中,并且只有在验证了所有内容后才插入。当然,两个并发事务之间可能存在争用条件,但这种情况不会经常发生,因此可以使用通用的“Oops”错误消息来处理它(或者在确实需要时重试事务)。

没有好的方法来做到这一点。问题是JPA本身并不验证DB约束。它只是将此检查委托给底层数据库。因此,具体的异常由JDBC驱动程序抛出,并由
PersistenceException
包装。显然,您可以调用
pe.getCause()
(甚至可能调用两次-查看使用调试器引发的异常类型)并尝试处理异常消息。但请注意,这可能取决于底层数据库和/或其JDBC驱动程序


但是:通常,创建基于异常的流是一种非常糟糕的做法。您应该自己验证应用程序级别的“约束”,如果可能存在唯一的约束冲突,则不要尝试执行该操作。无论如何,如果它发生了,则无事可做:用户应再次尝试执行该操作。用户不应该执行“错误”操作:用户界面应该保护他

我只发布了一小部分代码,我稍后回滚事务,但我仍然循环直到数据结束,所以我不能发回所有错误的内容。只是这个应用程序将来会被很多用户使用,我是说很多,所以我想限制查询的数量。这个特殊的表可能会被管理员使用,而且很少使用,但我仍然在寻找最好的方法来处理这些事情。所以检查uniques的最佳方法是在每次插入/更新之前进行查询以检查重复?不,我会立即得到异常,但由于我使用的是实体事务,因此通过捕获此项,我的事务将只进行回滚,所以。commit()将导致我发生一个真正的错误,从而破坏EJB。@Syfor:如果您想要一条准确的错误消息,告诉用户此字段的名称和对象不正确,是的,您应该使用查询。您可以使用单个查询一次检查所有名称:
从foo foo中选择foo.name,其中foo.name in:enteredNames
将在单个查询中返回所有已存在的名称。我重复一遍,在实体管理器抛出不可恢复的异常后尝试使用它是一个糟糕的主意。好的,一切正常,将您的答案标记为正确,因为它包含了大部分有用的信息:)谢谢。