5

我的应用程序使用 JPA+JavaDB,当我尝试持久化违反约束的对象时,我在控制台上得到SQLIntegrityConstraintViolationException 。

没关系,但我无法捕捉到那个异常,为什么?


这是我想捕获异常的代码示例。如果我查看persist() 的文档,则没有 SQLIntegrityConstraintViolationException 的迹象。

em.getTransaction().begin();
em.persist(object);
em.getTransaction().commit();

控制台堆栈跟踪的一部分:

[EL Warning]: 2013-09-15 16:38:57.571--UnitOfWork(459929151)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: A instrução foi interrompida, porque iria gerar um valor duplicado da chave em uma restrição de chave primária ou de unicidade identificada por 'SQL130819202336721' definida em 'CORRETORA'.
Error Code: -1
Call: UPDATE CORRETORA SET NOME = ? WHERE (ID = ?)
    bind => [2 parameters bound]
Query: UpdateObjectQuery(Corretora[ id=7 ])
javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: A instrução foi interrompida, porque iria gerar um valor duplicado da chave em uma restrição de chave primária ou de unicidade identificada por 'SQL130819202336721' definida em 'CORRETORA'.
Error Code: -1
Call: UPDATE CORRETORA SET NOME = ? WHERE (ID = ?)
    bind => [2 parameters bound]
Query: UpdateObjectQuery(Corretora[ id=7 ])
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
    at br.meuspila.util.AbstractCrud.persist(AbstractCrud.java:50)
    at br.meuspila.corretora.CorretoraRN.persist(CorretoraRN.java:30)
    at br.meuspila.javafx.EditarCorretoraController$1.handle(EditarCorretoraController.java:66)
    at br.meuspila.javafx.EditarCorretoraController$1.handle(EditarCorretoraController.java:51)
...
4

3 回答 3

3

日志告诉你原因。被SQLIntegrityConstraintViolationException包裹在一个org.eclipse.persistence.exceptions.DatabaseException. 您可以捕获此异常并对SQLIntegrityConstraintViolationException

不知道你的代码,不可能告诉你在哪里改变它,但如果你真的想 catch SQLIntegrityConstraintViolationException,你必须在它被包裹在另一个异常之前这样做。

于 2013-09-15T19:48:53.800 回答
0

2019-12-18

我刚刚遇到了一个非常相似的问题EclipseLink,在服务器Maven上运行 Weblogic 12c并使用JTA.

persistence.xml我们有:

< property name="eclipselink.persistence-context.flush-mode"
    value="commit" />  

就我而言。我必须手动调用flush()EntityManager强制刷新,并在适当的时间和行(基本上在 中try block)发生异常,以便能够捕获它,处理它。

我的插入/更新/删除查询位于我的 JPA 提供程序缓存中,并且没有发送到数据库,因此不会发生此异常,因此代码无法捕获它。

自动地,它会被刷新并且异常会发生在事务边界的末尾,在我的例子中基本上是在方法的末尾,这显然在我的try{...}catch(Exception e){...}块之后很远,所以我无法捕捉到它。

日志中最终捕获的异常(我掩盖了一些不相关的信息):

javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - x.x.x.v00000000-0000000): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (XXXXX.UNIQUE_KEY_NAME) violated

相关伪代码:

    try {
            repository.update(entity);
            repository.getEntityManager().flush();
        } catch (Exception e ) {
            log.info(e.toString());  
            ...
        }
于 2019-12-18T19:53:02.430 回答
0
try{
    em.getTransaction().begin();
    em.persist(object);
    em.getTransaction().commit();
} catch (Exception e) { 
    if(e.getCause() != null && e.getCause().getCause() instanceof SQLIntegrityConstraintViolationException) {
        SQLIntegrityConstraintViolationException sql_violation_exception = (SQLIntegrityConstraintViolationException) e.getCause().getCause() ;
        log.error("SQLIntegrityConstraintViolationException has accured. " +  sql_violation_exception.getMessage());
    } else {
        log.error(e.getMessage());
    }
}
于 2020-07-16T15:27:32.843 回答