我正在使用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和Entity FooEntity之间进行映射。 Dozer在后台做的是实例化一个新的FooEntity并设置所有匹配的字段。 BarEntity也通过实例化进行克隆,并设置了FooEntity的“bar”成员。
发生这种情况后,将新的FooEntity对象传递给persist。抛出异常:
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注释来解决此问题,但是这限制了将来的用途,例如添加新Foo并附加了新的Bar。我在这里有一些解决方案吗?如果这个问题之前没有得到解决,我会感到惊讶,要么通过改变Dozer如何映射Foo的孩子或者Hibernate如何对一个独立的子实体作出反应。
答案 0 :(得分:0)
你能看一下你是否有一个包含此事的交易?如果您发布的第二位代码没有包含任何事务,那么当您尝试保留时,BarEntity
将与Hibernate会话分离,这将导致您提到的错误。
答案 1 :(得分:0)
我怀疑推土机的映射是罪魁祸首。尝试将属性copy-by-reference =“true”添加到FooImpl / FooEntity的属性栏。