Search code examples
javahibernatejpaplayframework

Using Play framework, persist Hibernate object after a database-related Exception


I'm a Play/Hibernate beginner trying to extend a Play 1.2.3 app I inherited that parses the contents of a file with unreliable data and attempts to persist it to the database.

I need a way to mark in the database when the app has a problem persisting its contents to the database. Before the app wasn't even catching the SQL exceptions and just crashing outright. So, I wrapped the whole thing in a try-catch block in hopes that within the catch block I could handle the error gracefully and record the failure in the database.

Roughly, this is what I updated the code to:

try {
   MyObject parent = new MyObject();
   // Persist the parent object and all of its child objects.  The SQL errors are 
   // occurring on the child objects.
   parent.save();
   // Do a bit more processing
   parent.status=1;
   parent.save(); 
}
catch {
   // This is what I'm trying to do -- set the failure status 
   // in the database to look at later
   parent.status = 0;
   parent.save();
}

MyObject inherits from:

package models;
import javax.persistence.*;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass
public class MyObjectModel extends play.db.jpa.GenericModel { .. }

The code as written above throws:

ERROR: current transaction is aborted, commands ignored until end of transaction block
ERROR ~ Could not synchronize database state with session

I tried calling parent.refresh() before save(), but that resulted in:

play.exceptions.JavaExecutionException: org.hibernate.exception.GenericJDBCException: 
could not load an entity: [models.MyObject#465655]

I tried create a new MyObject object and giving it the same values as the previous one, including the previously-fetched Hibernate ID (and calling merge()), but that resulted in:

PersistenceException occured : org.hibernate.PersistentObjectException: 
detached entity passed to persist: models.MyObject

If I don't give it the previously-fetched Hibernate ID, it throws:

ERROR: current transaction is aborted, commands ignored until end of transaction block
PersistenceException occured : org.hibernate.exception.GenericJDBCException: 
could not get next sequence value

I thought that the above was the best way to go, since that would keep me from cascading to all of the child objects, which I don't want to do (and which will obviously fail again).

Looking at the documentation, I'm out of ideas. All I want to do it write a status code to the database row of the just the parent object (not all of the problematic children) so that I can mark that there was a persistence failure here.


Solution

  • I guess that when you have such an exception the transaction is marked as rollback only (via JPA.setRollbackOnly(). And all you have to do is commit the current transaction and start a new one (via JPAPlugin.closeTx and startTx).