4

我正在使用 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”成员设置为来自数据库(通过 session.get(..) 检索)的现有 Bar(运行时是 BarEntity)。在 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 注释来解决这个问题,但这限制了未来的使用,比如添加一个新的 Foo 已经附加了一个新的 Bar 。我在这里缺少一些解决方案吗?如果这个问题以前没有在某个地方得到解决,我会感到惊讶,无论是通过改变 Dozer 如何映射 Foo 的子级或 Hibernate 如何对分离的子实体做出反应。

4

2 回答 2

0

你能看看你是否有围绕这个的交易吗?如果您发布的第二段代码没有包含任何事务,那么BarEntity当您尝试持久化时,它将与 Hibernate Session 分离,这将导致您提到的错误。

于 2011-01-04T16:11:07.583 回答
0

我怀疑推土机映射是罪魁祸首。尝试将属性 copy-by-reference="true" 添加到 FooImpl/FooEntity 的属性栏。

于 2011-02-03T10:14:09.477 回答