Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception Handling with JPA + Hibernate

I'm using JPA with Hibernate as the provider with container-managed transactions (JBoss AS 6.1.0.Final).

I'm trying to implement some fine grained exception handling because I have a particular exception hierarchy on my app so I can define what to do in every situation. So, I've been investigating for hours and I find the documentation vague and the examples somewhat raw because exception handling is always left out "for the sake of clarity" or is a simple try-catch block that handles Exception e.

For example, take this code:

public void deleteCompany(ICompany company) throws MyException1, MyException2 {
    if(entityManager != null){
        if(company !=null) {
            try {
                ICompany companyReference= entityManager.getReference(Company.class, company.getId());
                entityManager.remove(managedCompany);
                entityManager.flush();
            } catch(EntityNotFoundException companyDoesNotExist) {
                //Wrap & Throw
            }
        } else {
        throw new MyException1("An error occurred while attempting to save a null instance of a company");
        }
    } else {
        throw new MyException2("The entity manager instance is null");
    }   
}

The catch block is blank because that's where I'm stuck... I don't know which exception should I catch to alert the system that the user was attempting to delete a non-existent record.

My concrete question is: Can I catch Hibernate exceptions on that catch block or do I have to catch the JPA ones? I found some sources that claim that JPA wraps the exceptions of the providers but that sounds odd to me. I've also found that calling the flush() method makes it possible to catch the database-access and manipulation exceptions, since the transactions are managed by the container and thus the commitment comes in further steps after invoking deleteCompany.

Thank you.

EDIT: I'm wrapping the exceptions I catch with my own exceptions annotated with @ApplicationException(rollback=true), so I can throw them again and handle them more clearly.

EDIT 2: I've updated my code. The merge before the remove persists the company if it is not in the database, causing the remove to be successful everytime. Now the exceptions are being thrown and I'm testing how does it behave in different situations catching the JPA exceptions as suggested by Perception.

EDIT 3: Now it's working!, turns out the error was partially in my code because of that merge call. Getting the reference first and attempting a remove after does the trick, that way I was able to catch an EntityNotFoundException, wrap it and throw it again.

like image 948
Fritz Avatar asked Apr 17 '12 21:04

Fritz


People also ask

How exceptions are handled in hibernate?

Hibernate provides better handle than the JDBCException . Developers can use the try and catch block to handle the exceptions. Put the line of code that may cause an exception in a try block and according to that exception put the exception handler in the catch block.

Can we use JPA with Hibernate?

Hibernate is an implementation of JPA. Hence, the common standard which is given by JPA is followed by Hibernate. It is a standard API that permits to perform database operations. It is used in mapping Java data types with SQL data types and database tables.


1 Answers

You would definitely not be catching vendor exceptions because they get rolled into JPA exceptions. Note that you may be getting one of several exception types at the point in question:

  • IllegalArgumentException - for detached or non-entity objects
  • IllegalStateException - entity manager is closed
  • PersistenceException - at least, some subclass thereof. You can get this for any number of reasons, if there is no associated transaction and the call requires one, if a database constraint rejects the operation, if the transaction takes too long etc etc.

You really shouldn't be catching these exceptions at such a low level, unless you are planning to re-wrap them in a custom application exception of some sort. If you decide to go that route make sure to wrap the original exception, so that the stack trace is not lost.

It's worthy to note that all the exceptions generated by the JPA Entity Manager are runtime exceptions.

like image 137
Perception Avatar answered Oct 13 '22 23:10

Perception