Jpa 如何从EclipseLink捕获约束冲突异常?

Jpa 如何从EclipseLink捕获约束冲突异常?,jpa,jpa-2.0,eclipselink,Jpa,Jpa 2.0,Eclipselink,我在我的web应用程序中使用EclipseLink,很难优雅地捕获和处理它生成的异常。我从一个类似的问题上看出来,但我不知道如何解决或修复它 我的代码如下所示: public void persist(Category category) { try { utx.begin(); em.persist(category); utx.commit(); } catch (RollbackException ex) {

我在我的web应用程序中使用EclipseLink,很难优雅地捕获和处理它生成的异常。我从一个类似的问题上看出来,但我不知道如何解决或修复它

我的代码如下所示:

public void persist(Category category) {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
           // Log something
    } catch (HeuristicMixedException ex) {
           // Log something
    } catch (HeuristicRollbackException ex) {
           // Log something
    } catch (SecurityException ex) {
           // Log something
    } catch (IllegalStateException ex) {
           // Log something
    } catch (NotSupportedException ex) {
           // Log something
    } catch (SystemException ex) {
           // Log something
    }
}
public void persist(Category category) throws EntityExistsException {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
        throw new EntityExistsException(ex);
    } catch (HeuristicMixedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicRollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalStateException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NotSupportedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SystemException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    }
}
当使用违反唯一性约束的实体调用persist()时,容器会捕获并记录大量异常

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504):
  org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement
  was aborted because it would have caused a duplicate key value in a unique or 
  primary key constraint or unique index identified by 'SQL110911125638570' 
   defined on 'CATEGORY'.
 Error Code: -1
 (etc)
我尝试了以下方法:

    try {
        cc.persist(newCategory);        
    } catch (PersistenceException eee) {
        // Never gets here
        System.out.println("MaintCategory.doNewCateogry(): caught: " + eee);
    } catch (DatabaseException dbe) {
        // Never gets here neither
        System.out.println("MaintCategory.doNewCateogry(): caught: " + dbe);            
    }

我意识到使用DataBaseException是不可移植的,但我需要从某个地方开始。例外情况永远不会被发现。有什么建议吗?

EclipseLink应该只抛出persistenceException或RollbackException,具体取决于您在EntityManager上调用的环境和操作顺序。 您的日志记录级别是多少?您可能看到EclipseLink记录了这些异常,但只是作为回滚异常的原因抛出


您可以使用PU属性关闭异常日志记录,但出于诊断目的,通常最好允许EclipseLink记录异常。

看起来我不会在这个问题上获得更多的活动,因此我将发布我的工作并将其保留。许多网络搜索都没有找到多少有用的东西。我本以为这是一个教科书案例,但我发现没有一本教程涵盖这一点

在EclipseLink的这种情况下,当违反SQL约束时,可以捕获的异常是RollBackException,这是em.commit()调用的结果。因此,我修改了persist方法,如下所示:

public void persist(Category category) {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
           // Log something
    } catch (HeuristicMixedException ex) {
           // Log something
    } catch (HeuristicRollbackException ex) {
           // Log something
    } catch (SecurityException ex) {
           // Log something
    } catch (IllegalStateException ex) {
           // Log something
    } catch (NotSupportedException ex) {
           // Log something
    } catch (SystemException ex) {
           // Log something
    }
}
public void persist(Category category) throws EntityExistsException {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
        throw new EntityExistsException(ex);
    } catch (HeuristicMixedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicRollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalStateException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NotSupportedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SystemException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    }
}
因此,调用者捕捉到EntityExistsException,并采取适当的操作。日志仍然充满内部异常,但可以稍后关闭

我意识到这有点滥用了EntityExistSexceception的意图,该概念通常仅在重复使用实体ID字段时使用,但对于用户应用程序而言,这并不重要


如果有人有更好的方法,请发表新的答案或评论。

我使用的是Spring Boot 1.1.9+EclipseLink 2.5.2。这是捕获ConstraintViolationException的唯一方法。请注意,my
handleError(ConstraintViolationException)
是一个非常简单的实现,它只返回找到的第一个冲突

注意,当我切换到Hibernate 4.3.7和Hibernate Validator 5.1.3时,这段代码也是必需的

似乎将
PersistenceExceptionTranslationPostProcessor exceptionTranslation()
添加到我的persistenceJavaConfig类中也没有效果


import javax.persistence.RollbackException;
导入javax.validation.ConstraintViolation;
导入javax.validation.ConstraintViolationException;
导入org.springframework.http.HttpStatus;
导入org.springframework.http.ResponseEntity;
导入org.springframework.transaction.TransactionSystemException;
导入org.springframework.web.bind.annotation.ControllerAdvice;
导入org.springframework.web.bind.annotation.ExceptionHandler;
@控制器建议
类GlobalExceptionHandler
{
@ExceptionHandler(TransactionSystemException.class)
公共响应处理错误(最终交易系统例外tse)
{
if(tse.getCause()!=null&&tse.getCause()回滚异常实例)
{
最终回滚异常re=(回滚异常)tse.getCause();
if(re.getCause()!=null&&re.getCause()instanceof ConstraintViolationException)
{
返回handleError((ConstraintViolationException)re.getCause());
}
}
掷骰子;
}
@ExceptionHandler(ConstraintViolationException.class)
@抑制警告(“未使用”)
公共责任处理错误(最终约束例外cve)
{
对于(final constraintviolations v:cve.getConstraintViolations())
{
返回新的响应属性(新对象()
{
公共字符串getErrorCode()
{
返回“验证错误”;
}
公共字符串getMessage()
{
返回v.getMessage();
}
},HttpStatus.BAD_请求);
}
投掷cve;
}
}
我用这个

if (!ejbGuardia.findByPkCompuestaSiExiste(bean.getSipreTmpGuardiaPK())) {
    ejbGuardia.persist(bean);
    showMessage(ConstantesUtil.MENSAJE_RESPUESTA_CORRECTA, SEVERITY_INFO);
} else {
    showMessage("Excel : El registro ya existe. (" + bean.toString() + ")  ", SEVERITY_ERROR);
}
我的职能是:

public boolean findByPkCompuestaSiExiste(Object clasePkHija) throws ClassNotFoundException {
    if (null != em.find(this.clazz, clasePkHija)) {
        return true;
    }
    return false;
}

因此,我不需要为每个Persist编写验证程序,它在my DAO类中很常见。

编辑persistence.xml并添加以下属性:

property name=“eclipselink.exception handler”value=“your.own.package.path.YourOwnExceptionHandler”

现在创建类YourOwnExceptionHandler(在正确的包上)。它需要实现org.eclipse.persistence.exceptions.ExceptionHandler

创建一个非参数构造函数和所需的方法handleException(…)


在这个方法中,您可以捕获异常

2019-12-18

由于这是一个被广泛接受的问题,而且我刚刚遇到了一个与
EclipseLink
非常相似的问题,在
Maven
多模块web应用程序中,运行在
Weblogic 12c
服务器上,使用
JTA
,我将在这里发布我的解决方案,希望为某人节省几个小时

persistence.xml
中,我们有:

< property name="eclipselink.persistence-context.flush-mode"
    value="commit" />
相关伪代码:

    try {
            repository.update(entity);
            repository.getEntityManager().flush();
        } catch (Exception e ) {
            log.info(e.toString());  
            ...
        }

正如您所说,我希望在开发模式期间保持登录,以便在系统错误发生时能够捕获它们。但真正的问题是,当我调用commit()方法时,我似乎无法捕获异常,因此我可以在屏幕上抛出一条消息。“DataBaseException不可移植”是什么意思?谢谢@DataBaseException类是由org.eclipse定义的,而不是JPA规范。所以这个李