I am using Hibernate 3 and have a specific problem when saving a new object that has a relationship with an existing separate object. The easiest way to explain this is through code samples. I have two objects: FooEntity and BarEntity, of which 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 freely define getters for various fields. There are corresponding classes FooImpl and BarImpl, which are essentially entity objects without annotations.
What I'm trying to do is build a new instance of FooImpl and save it after setting several fields. The new Foo instance will have its member "bar" set to the existing Bar (BarEntity runtime) from the database (obtained through session.get (..)). After FooImpl has all its properties, Apache Dozer is used to display between the "domain" object FooImpl and Entity FooEntity. What Dozer does in the background creates a new FooEntity and sets all the appropriate fields. BarEntity is also cloned through instantiation and sets the member to "FooEntity".
After that, the passage of the new FooEntity object is saved. This throws an exception:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.company.entity.BarEntity
Below is the code that executes
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 was able to solve this problem by deleting or changing the @Cascade annotation, but this limits future use, for example, adding a new Foo with a new Bar already attached to it. Is there any solution here, am I missing? I would be surprised if this problem was not solved somewhere earlier, either by changing how Dozer Maps defines Foo children, or how Hibernate reacts to a separate child object.