Question

My application uses JPA+JavaDB and when I try to persist an object that violates a constraint I get SQLIntegrityConstraintViolationException on console.

That is OK but I can't catch that exception, why?


This is a sample of my code where I would like to catch the exception. If I look at the documentation of persist(), there is no sign of SQLIntegrityConstraintViolationException.

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

Part of the console stack trace:

[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)
...
Était-ce utile?

La solution

The log is telling you why. The SQLIntegrityConstraintViolationException is wrapped inside an org.eclipse.persistence.exceptions.DatabaseException. You can catch this exception and do something about the SQLIntegrityConstraintViolationException

Not knowing your code, it's impossible to tell you where to change it, but if you wanted to really catch SQLIntegrityConstraintViolationException, you would have to do so before it got wrapped in the other exception.

Autres conseils

2019-12-18

I just had a very similar issue with EclipseLink, in a Maven multi module web application running on Weblogic 12c server and using JTA.

In the persistence.xml we are having:

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

In my case. I had to manually call flush() on EntityManager to force flush and the exception to occur at proper time and line (basically in the try block) to be able to catch it, handle it.

My insert/update/delete query was sitting in my JPA provider cache, and not sent to the database, this exception couldn't occur so the code couldn't caught it.

Automatically, it would have been flushed and the exception would have occured at the end of the transaction boundary, basically at the end of the method in my case, which is obviously far after my try{...}catch(Exception e){...} block, so I was not able to catch it.

The final caught exception in the log (I have masked some not related info):

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

Related pseudo code:

    try {
            repository.update(entity);
            repository.getEntityManager().flush();
        } catch (Exception e ) {
            log.info(e.toString());  
            ...
        }
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());
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top