EJB3 和手动层次结构持久性
Posted
技术标签:
【中文标题】EJB3 和手动层次结构持久性【英文标题】:EJB3 and manual hierarchy persistence 【发布时间】:2009-02-25 10:24:58 【问题描述】:我有一个遗留数据库,我正在使用 EJB3 对其进行建模。数据库的状态很差,我们对如何插入数据库有一些不寻常的限制。现在我想在适合数据库结构的层次结构中对数据库进行建模,但我希望能够单独手动插入每个实体,而不需要持久性管理器尝试持久化实体子项。
我正在尝试类似以下的内容(样板被省略):
@Entity
@Table(name = "PARENT_TABLE")
public class Parent
@Id
@Column(name = "ID")
int id;
@OneToMany
List<Child> children;
@Entity
@Table(name = "CHILD_TABLE")
public class Child
@Id
@Column(name = "ID")
int id;
现在这会引发异常:
java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST
现在我知道实体没有被标记为 PERSIST - 我不希望 EntityManager 保留它!我希望能够先坚持父母,然后是孩子——但不是在一起。想要这样做是有充分理由的,但它似乎不想玩。
【问题讨论】:
【参考方案1】:欢迎来到 JPA 配置这个令人毛骨悚然的地方。
在您的情况下,您有两个选择:
-
手动持久化新对象;或
自动持久化它。
要自动持久化它,您需要注释关系。这是一个常见的一对多习语:
@Entity
@Table(name = "PARENT_TABLE")
public class Parent
@Id private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private Collection<Child> children;
public void addChild(Child child)
if (children == null)
children = new ArrayList<Child>();
child.setParent(parent);
children.add(child);
@Entity
@Table(name = "CHILD_TABLE")
public class Child
@Id private Long id;
@ManyToOne
private Parent parent;
public void setParent(Parnet parent)
this.parent = parent;
Parent parent = // build or load parent
Child child = // build child
parent.addChild(child);
由于级联持久化,这将起作用。
注意:您必须自己在 Java 级别管理关系,因此手动设置父级。这很重要。
没有它,您需要手动持久化对象。您需要一个 EntityManager 来执行此操作,在这种情况下,它很简单:
entityManager.persist(child);
此时它将正常工作(假设一切正常)。
对于纯粹的子实体,我倾向于使用注释方法。这更容易。
我将提到 JPA 的一个问题:
Parent parent = new Parent();
entityManager.persist(parent);
Child child = new Child();
parent.addChild(child);
现在我对此有点生疏,但我相信如果您这样做可能会遇到问题,因为在添加子项之前父项已被持久化。无论您做什么,都要小心并检查这种情况。
【讨论】:
那么如果我将级联属性设置为PERSIST,并使用实体管理器来持久化父级,那么EntityManager是否也会尝试持久化子级?如果是这样,这不是我想要的,因为我需要能够独立地坚持 Parent 和 Child。 顺便说一句,反向链接的省略是故意的——我只想对关系进行单向建模。这会导致问题,即是否需要双向关系? 父母对孩子的一种方式可能会有问题。有点生锈。从孩子到父母的一种方式更容易。 P->C 的问题是外键驻留在孩子中,因此需要映射。能详细说说你的情况吗? 顺便说一句,“坚持”并不完全意味着您在 JPA 中的想法。它只是使对象成为一个托管对象,如果事务被提交,则可以保存(但假设这一切都在事务中,则保存直到提交才会发生)。为什么要独立保存?好奇。 对于一种方式的父子关系,您需要一个 @JoinTable 用于它们之间的映射。以上是关于EJB3 和手动层次结构持久性的主要内容,如果未能解决你的问题,请参考以下文章