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:
Code:
@Entity
public class FooEntity implements Foo{
@Id
private Long id;
@ManyToOne(targetEntity = BarEntity.class)
@JoinColumn(name = "bar_id", referencedColumnName = "id")
@Cascade(value={CascadeType.SAVE_UPDATE})
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 FooEntity, and persist it. the new Foo instance will have its 'bar' member set to an existing Bar Entity from the database. This works fine if that is all I am doing. The wrinkle here is we are using Apache Dozer to map between our domain objects (like FooImpl) and our Entities (FooEntity).
While performing the Mapping, new Instances of FooEntity and BarEntity are created, and the appropriate fields are set. The returned FooEntity then has a field bar of BarEntity which is detached. When the mapped FooEntity object is then passed to the Session to persist, the exception:
Code:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.company.entity.BarEntity
is thrown. This all occurs within the same transaction. Below is in code the steps that are occurring
Code:
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.