Bean 映射 (Dozer) 的 Hibernate 持久性问题
我正在使用 Hibernate 3,并且在保留与现有分离实体有关联的新实体时遇到了特定问题。解释这一点的最简单方法是通过代码示例。我有两个实体,FooEntity 和 BarEntity,其中一个 BarEntity 可以与许多 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 和 Bar 是松散地定义各个字段的 getter 的接口。有相应的 FooImpl 和 BarImpl 类,它们本质上只是没有注释的实体对象。
我想做的是构造一个新的 FooImpl 实例,并在设置多个字段后保留它。新的 Foo 实例将其“bar”成员设置为数据库中的现有 Bar(运行时为 BarEntity)(通过 session.get(..) 检索)。在 FooImpl 设置完所有属性后,将使用 Apache Dozer 在“域”对象 FooImpl 和实体 FooEntity 之间进行映射。 Dozer 在后台执行的操作是实例化一个新的 FooEntity 并设置所有匹配字段。 BarEntity 也通过实例化进行克隆,并设置 FooEntity 的“bar”成员。
发生这种情况后,传递新的 FooEntity 对象来持久化。这引发了异常:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.company.entity.BarEntity
下面是代码中正在发生的步骤,
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);
我已经能够通过删除或更改 @Cascade 注释来解决此问题,但这限制了将来的使用,例如添加附加了新 Bar 的新 Foo已经。我在这里缺少一些解决方案吗?如果这个问题以前没有通过改变 Dozer 映射 Foo 的子实体的方式或 Hibernate 对分离的子实体的反应方式来解决,我会感到惊讶。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我怀疑推土机映射是罪魁祸首。尝试将属性 copy-by-reference="true" 添加到 FooImpl/FooEntity 的属性栏。
I suspect the Dozer mapping is to blame. Try adding the attribute copy-by-reference="true" to the property bar of FooImpl/FooEntity.
您能看看您是否有围绕此进行的交易吗?如果您发布的第二位代码中没有包含任何事务,那么当您尝试持久保存时,
BarEntity
将从 Hibernate Session 中分离,这将导致您提到的错误。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.