Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate (JPA) cascade - retrieve id from child

Tags:

orm

hibernate

jpa

I have a parent class with the following field with cascading option:

public class Parent {
  @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
  @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
  private final Set<Child> children = new HashSet<Child>();
  public addChild(Child child) { children.add(child); }
}

In my application I want to add a child and then call JPA merge on the parent class, automatically persisting my new child. This all works, however, the origional child reference I inserted into my parent object has changed, meaning I cannot retrieve the ID of my persisted child. Is there any way I can tell hibernate to re-use my old child reference instead of making a new one? during the merge

like image 407
Jeroen Avatar asked Feb 01 '10 15:02

Jeroen


2 Answers

Just get the merged instance of your parent:

parent = entityManager.merge(parent);

Update:

What you want is not possible. Either manually merge() the child, and then add it to the parent, or get the new child instance from the parent collection and use it instead.

like image 143
Bozho Avatar answered Nov 15 '22 09:11

Bozho


For many actions, Hibernate generates an event that can be listened for and some support code for listening.

If you're using Spring in conjunction with Hibernate, for instance, you can register a class org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener as a listener for hibernate's merge event (from I think spring-orm.jar) by putting the following in your hibernate.cfg.xml (or whatever file is referenced in your spring setup for hibernate config):

    <event type="merge">
        <listener class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
    </event>

or by adding an map in your sessionFactory bean:

    <bean id="sessionFactory" 
          class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
          p:dataSource-ref="dataSource">
    <property name="configLocation" value="WEB-INF/classes/hibernate.cfg.xml"/>
    <property name="eventListeners">
            <map>
                    <entry key="merge">
                            <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
                    </entry>
            </map>
    </property>

If you do either of these, this listener should set the id in the original object. If you're not using Spring, there's likely a way to get a listener connected that's similar to one of these.

I haven't tested the child behavior you're looking for, but I'm pretty sure that a merge on the parent will trigger a merge on the child so that the listener will be called for both.

The setup for JPA might be different, but I suspect it's possible, and hope this gives clues.

like image 30
Don Roby Avatar answered Nov 15 '22 09:11

Don Roby