简体   繁体   中英

JPA2 unique constraint: do I really need to flush?

I have a DAO where I need to catch an unique constraint exception. To do this, the only working solution is to flush my EntityManager after the persist. Only then I come into a catch block where I have to filter out the exception. And, my DAO method needs to be wrapped in a transaction (REQUIRES_NEW) otherwise I have the RollBackException.

Am I doing something wrong?

try {
        em.persist(myObject);
        em.flush();
    } catch (PersistenceException ex) {
        if (ex.getCause() != null) {
            String cause = ex.getCause().toString();
            if (cause != null) {
                if (cause.contains("org.hibernate.exception.ConstraintViolationException")) {
                    logger
                            .error("org.hibernate.exception.ConstraintViolationException: possible unique constraint failure on name");
                    throw ex;
                }
            }
        }
    }

Am I doing something wrong?

EntityManager#persist() won't trigger an immediate insert (unless you are using an IDENTITY strategy). So if you want to actually write the in memory changes to the database and get a chance to catch a constraint violation, you have to flush() "manually" (although even doing so doesn't strictly guarantee anything, your database could be configured to use deferred constraints ).

In other words, what you're doing is IMO just the right way to go.


I have a service method with a @Transactional on it (REQUIRED) called addNewObject(). In this method some stuff happens that might throw an exception (and thus rollback the transaction). One of these calls is a call to the DAO method addObject. This one might fail because of the unique constraint. Now, if I do flush, the object will be persisted if there is no unique violation. However, within the service there might still be something else that causes the method to throw an exception.

I think that you are confusing flush and commit . If something goes wrong outside addObject and throws an unrecoverable exception (but inside the same transaction), the whole transaction will be rolled back, including the INSERT statements corresponding to the persist() calls. To sum up, flush != commit .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM