You really should not try to do this. As mentioned in another answer, and quoting Hibernate Docs, no exception thrown by Hibernate should be considered as recoverable. This can lead to some difficult search / debugging tasks, especially with an automatic crash in sleep mode.
A clean way to solve this problem is to check these limitations before inserting an object. Use the query to check if the database restriction is violated.
public Object foo() { if (!objectExists()) { insertStuff(); return stuff(); }
I know this seems a little painful, but the only way you probably know which restriction has been violated (you cannot get this information from Hibernate exceptions). I believe this is the cleanest solution (the safest, at least).
If you still want to recover from the exception, you will have to make some changes to your code.
As already mentioned, you can manage transactions manually, but I do not recommend doing this. The JTA API is really cumbersome. Also, if you use Bean Managed Transaction (BMT), you will have to manually create transactions for each method in your EJB, all or nothing.
On the other hand, you can reorganize your methods so that the container uses a different transaction for your request. Something like that:
@Stateless public class Foo { ... @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public Object foo() { try { entityManager.insert(stuff); return stuff; } catch (PersistenceException e) { if (e.getCause() instanceof ConstraintViolationException) {
When foo () is called, the current transaction (T1) will be suspended and the container will create a new one (T2). When an error occurs, T2 will be deployed and T1 will be restored. When load () is called, it will use T1 (which is still active).
Hope this helps!
Andre Rodrigues
source share