How to handle JPA unique constraint violations?
How can I find out that a unique constraint was violated?
Exception are chained, you have to call getCause()
recursively to get the provider specific exception (and maybe go down to the SQLException
) to translate it into something your application can handle nicely for your user. The following will print the chain of exception:
for (t = e.getCause(); t != null; t = t.getCause()) {
logger.debug("Exception:" + t);
}
For the exception handling and the "translation", you could do something like what Spring does (see the various JpaDialect
classes, e.g. HibernateJpaDialect
to get an idea).
All this is not nice, this code won't be portable and finding what attribute(s) caused the violation won't be easy. This somehow confirms that there is no elegant and portable way to handle constraint violations in JPA.
Best way to prevent unique constraint violations with JPA
Your last solution is the right one, IMO. Search for the keyword type, and if not found, create it.
Catching the exception is not a good option because
- it's hard to know which exception to catch and make your code portable across JPA and DB engines
- The JPA engine will be in an undetermined state after such an exception, and you should always rollback in this case.
Note however that with this technique, you might still have two transactions searching for the same type in parallel, and then try to insert it in parallel. One of the transaction will rollback, but it will be much less frequent.
Catching constraint violations in JPA 2.0
When I insert records with a duplicate value for the link attribute, EclipseLink does not throw a EntityExistsException
Yes, and a JPA provider is not supposed to throw an EntityExistException
in that case, you won't get an EntityExistException
on something else than the primary key.
(...) but throws a DatabaseException, with the message explaining that the unique constraint was violated.
This is very WRONG from EclipseLink, a JPA provider should throw a PersistenceException
or a subclass but certainly not a specific exception like o.e.p.e.DatabaseException
. This is a bug and should be reported as such as I already mentioned in a previous answer.
This doesn't seem very usefull, as there would not be a simple, database independent, way to catch this exception. What would be the advised way to deal with this?
Same answer as above, see my previous answer.
Best practice propagating Unique Violation Exceptions to UI
Approach 1 will not work in a concurrent scenario! -- There is always a change that somebody else insert a new database record after you checked but before you added your database record. (except you use isolation level serializable, but this is highly unlikely)
So you have to handle the DB constraint violation exceptions. But I recommend to catch the database exception that indicates the unique violation and throw a more meaning full like you suggested in Approach 1.
Unique Constraint error thrown at the end of @Transactional block
The error happens in the interceptor because right before committing the transaction, Hibernate needs to flush pending changes to the database. During that flush, the database exception happens. You can flush manually by calling saveAndFlush
on the repository.
Related Topics
Parameter 0 of Constructor in Required a Bean of Type 'Java.Lang.String' That Could Not Be Found
How to Click an Li Inside a Ul Using Selenium Webdriver
Setonclicklistener() on a Null Object Reference Error
How to Avoid Nullpointerexception With an Empty Cell Using Poi
Mock Objects Created Inside Method Under Test to Verify the Arguments Passed
How to Update Thousands of Records into MySQL Db in Milliseconds
How to Use Junit to Test Asynchronous Processes
Getresourceasstream Returns Null When Reading Properties File
How to Get Spring Boot to Automatically Create Database Schema
How to Quickly Check If Url Server Is Available
Rounding to the Nearest Hundered-Thousandths
How to Check Whether Kafka Server Is Running
Shifting Characters Within a String
Java.Lang.Noclassdeffounderror: Lorg/Apache/Logging/Log4J/Logger; But the Artifact Exists
Java 8 Convert Utc Time to Edt/Est So That Date Remains the Same
Java Jackson Deserialization of Nested Objects
How Is This Wrong - Hackerrank Loop in Java
How to Fix Mass Assignment: Insecure Binder Configuration (Api Abuse, Structural) in Java