Reputation: 984
Why doesn't JPA throw an exception for a unique constraint violation in the method where I do the merge? Instead, I see an exception thrown some other place in my code.
I want to get message of exceptions like (Update Error), but it doesn't catch the exception.
I would like get this response:
{
"errorMessage": "Update Error",
"errorCode": 404,
"documentation": ""
}
Instead, in console I got this error :
Caused by: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
.....
...
Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
.....
.....
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
......
.....
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (DEMAND_TD_CODE) violated
.....
....
Here is where I do the update:
@Override
public Demand updateDemand(Demand demand) throws DemandExceptions {
try {
Demand demandToUpdate = entityManager.merge(demand);
} catch (PersistenceException e) {
throw new DemandExceptions("Update Error");
}
return demandToUpdate;
}
DemandeExceptions.java
public class DemandeExceptions extends Exception implements Serializable {
private static final long serialVersionUID = 1L;
public DemandeExceptions (String message) {
super(message);
}
}
@Provider
public class DemandExceptionsMapper implements ExceptionMapper<DemandeExceptions >{
@Override
public Response toResponse(DemandeExceptions ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 404, "");
return Response.status(Status.NOT_FOUND)
.entity(errorMessage)
.build();
}
}
ErrorMessage.java
@XmlRootElement
public class ErrorMessage {
private String errorMessage;
private int errorCode;
private String documentation;
..
}
Upvotes: 2
Views: 4913
Reputation: 6487
In order to improve performance, most JPA implementations cache the DB operations rather than hit the DB on each JPA method call. This means that when you call merge()
the change is recorded in the Java data structures that the JPA implementation is managing, but no update has occurred yet in the database.
The JPA implementation does not detect problems like unique constraint violations - that is left to the database.
This means that the unique constraint violation does not occur within the try block that catches the PersistenceException. Instead, the exception is thrown when JPA decides that it needs to flush that update to the database. This automatic flush often occurs when the transaction is committed, but it may happen sooner (e.g., if a query needs to be executed against the updated table).
You can manually flush the JPA state by calling EntityManager.flush()
. If you do this within the try block, you will get the PersistenceException where you thought you would.
try {
Demand demandToUpdate = entityManager.merge(demand);
entityManager.flush();
} catch (PersistenceException e) {
throw new DemandExceptions("Update Error: " + e.getMessage());
}
Upvotes: 6
Reputation: 31
These are some issues that could cause the error:
Upvotes: 0
Reputation: 46
Exception in fact does get caught, but you lose the original message, consider updating the catch block as follows:
throw new DemandExceptions("Update Error, original message: " + e.getMessage());
Upvotes: 0