【问题标题】:How to catch java.sql.SQLIntegrityConstraintViolationException?如何捕获 java.sql.SQLIntegrityConstraintViolationException?
【发布时间】:2013-09-19 22:31:29
【问题描述】:

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

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


这是我想要捕获异常的代码示例。如果我查看documentation of 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)
...

【问题讨论】:

    标签: java jpa javadb


    【解决方案1】:
    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());
        }
    }
    

    【讨论】:

      【解决方案2】:

      2019-12-18

      我刚刚在Maven 多模块Web 应用程序中遇到了与EclipseLink 非常相似的问题,该应用程序在Weblogic 12c 服务器上运行并使用JTA

      persistence.xml 我们有:

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

      就我而言。我不得不在EntityManager 上手动调用flush() 以强制刷新,并且异常发生在适当的时间和行(基本上在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());  
                  ...
              }
      

      【讨论】:

        【解决方案3】:

        日志告诉你原因。 SQLIntegrityConstraintViolationException 包裹在 org.eclipse.persistence.exceptions.DatabaseException 中。你可以捕捉到这个异常并对SQLIntegrityConstraintViolationException做点什么

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

        【讨论】:

        • 谢谢,这个日志让我很困惑。
        • 现在我看到原来的异常是 javax.persistence.RollbackException (来自 em.getTransaction().commit() )。如果我尝试捕获 SQLIntegrityConstraintViolationException 或 DatabaseException 我没有成功。我的帖子经过编辑以添加代码示例。
        • @ceklock 你必须抓住包裹其他人的那个。通过调试应该可以找到。
        • 能否请您发布解决方案。我有同样的问题,不知道要捕获哪个异常。
        • @VijayKumar 什么解决方案?捕获堆栈跟踪顶部的任何异常。
        猜你喜欢
        • 2014-12-26
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-10
        • 2021-09-11
        • 1970-01-01
        • 2012-03-27
        相关资源
        最近更新 更多