How do I get Hibernate 4 to stop throwing "Single Instance Deletion"?

I need to use Hibernate 4.1.7 in my project. Unfortunately I don't have to upgrade to a newer version.

In my context, I have a master detail situation. So, I download the master object and display it on the web page with all its details. I can change both the master and the details as I like, even including new details. My save code looks like this:

@Override
@Transactional
public void save(Entity entity) {
    Session session = entityManager.unwrap(Session.class);
    session.saveOrUpdate(entity);
    session.flush();
}

      

The problem arises when I try to remove a part. The code below shows how this is done:

myMaster.getDetails().remove(myDetail);

      

I expect Hibernate to track changes over the main object (it lost an instance of the detail from the list item), but when I call the method save()

it throws java.lang.IllegalArgumentException: Removing a detached instance xxxx#yyyy

.

I understand the concept if I'm trying to delete an individual instance, but I don't understand why the just deleted instance is considered disconnected by Hibernate.

Any ideas?

TIA!

+3


source to share


1 answer


All you need to do to make it work as you expect (so that Hibernate will check the entire object graph):

@Override
@Transactional
public Entity save(Entity entity) {
    return entityManager.merge(entity);
}

      

Of course, make sure the operation is MERGE

cascaded from master to detail ( CascadeType.MERGE

or CascadeType.ALL

) and is orphanRemoval

set to collect data. If orphanRemoval

not, you need to explicitly delete the data (otherwise Hibernate will delete the associated children when they are no longer associated with their parents, which is clearly not desirable).

Also, be sure to use the result of the operation MERGE

after it always returns a copy of the passed single instance (the passed instance does not change). This is especially important when saving new instances, since the identifiers are specified in the copy.



However, you pay the penalty for reloading the object graph from the db, but if you want everything to be done automatically, Hibernate has no other way to check what actually changed, other than comparing it to the current state in the db.

Now, explanations of what you observed in your attempts:

  • The master you are saving is disabled. You load it in one transaction (persistent context / session) and store it in another.

  • It works fine with saveOrUpdate

    when you update it:

    Either save (object) or update (object) this instance, depending on when you enable checks for unsaved values ​​(see the manual for a discussion of checking for unsaved values).

    Parameters:

    object - a transient or detached instance containing a new or updated state

    As stated in the document, it is designed to work with single and temporary instances.

  • You tried to merge, but you got an exception telling you that there is already an object with the same ID. The only explanation is that you've tried something like this:

    @Override
    @Transactional
    public void save(Entity entity) {
        entity = entityManager.merge(entity);
        Session session = entityManager.unwrap(Session.class);
        session.saveOrUpdate(entity);
        session.flush();
    }
    
          

    Then an exception is thrown as described in the update

    javadoc:

    Update a persistent instance with the ID of the given single instance. If a persistent instance exists with the same identifier, an exception is thrown.

    So, you merged the instance into the current persistence context and then tried saveOrUpdate

    it (which is delegated update

    ) and this resulted in an exception, since you shouldn't update a single instance while it's already persistent in the current persistence context (otherwise the persistence will expire).

    You don't need to do this, just merge, and at the end of the transaction, Hibernate will messily validate the objects and automatically flush the changes to the db.

+5


source







All Articles