Question

I am using Hibernate 3, and having a particular issue when persisting a new Entity which has an association with an existing detached entity. Easiest way to explain this is via code samples. I have two entities, FooEntity and BarEntity, of which a BarEntity can be associated with many FooEntity:

@Entity
public class FooEntity implements Foo{

    @Id
    private Long id;

    @ManyToOne(targetEntity = BarEntity.class)
    @JoinColumn(name = "bar_id", referencedColumnName = "id")
    @Cascade(value={CascadeType.ALL})
    private Bar bar;    

}

@Entity
public class BarEntity implements Bar{

    @Id
    private Long id;

    @OneToMany(mappedBy = "bar", targetEntity = FooEntity.class)
    private Set<Foo> foos;
}

Foo and Bar are interfaces that loosely define getters for the various fields. There are corresponding FooImpl and BarImpl classes that are essentially just the entity objects without the annotations.

What I am trying to do is construct a new instance of FooImpl, and persist it after setting a number of fields. The new Foo instance will have its 'bar' member set to an existing Bar (runtime being a BarEntity) from the database (retrieved via session.get(..)). After the FooImpl has all of its properties set, Apache Dozer is used to map between the 'domain' object FooImpl and the Entity FooEntity. What Dozer is doing in the background is instantiating a new FooEntity and setting all of the matching fields. BarEntity is cloned as well via instantiation and set the FooEntity's 'bar' member.

After this occurs, passing the new FooEntity object to persist. This throws the exception:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.company.entity.BarEntity

Below is in code the steps that are occurring

FooImpl foo = new FooImpl();
//returns at runtime a persistent BarEntity through session.get()
Bar bar = BarService.getBar(1L);
foo.setBar(bar);

...

//This constructs a new instance of FooEntity, with a member 'bar' which itself is a new instance that is detached)
FooEntity entityToPersist = dozerMapper.map(foo, FooEntity.class);

...

session.persist(entityToPersist);

I have been able to resolve this issue by either removing or changing the @Cascade annotation, but that limits future use for say adding a new Foo with a new Bar attached to it already. Is there some solution here I am missing? I would be surprised if this issue hasn't been solved somewhere before, either by altering how Dozer Maps the children of Foo or how Hibernate reacts to a detached Child Entity.

Was it helpful?

Solution

I suspect the Dozer mapping is to blame. Try adding the attribute copy-by-reference="true" to the property bar of FooImpl/FooEntity.

OTHER TIPS

Could you take look whether or not you have a transaction wrapped around this? If there is no transaction wrapped around the second bit of code you posted, then the BarEntity will be detached from the Hibernate Session by the time you try to persist, which will cause the error you mentioned.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top