JPA:如何具有相同实体类型的一对多关系 [英] JPA: How to have one-to-many relation of the same Entity type

查看:149
本文介绍了JPA:如何具有相同实体类型的一对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个实体类A。 A类可能有相同类型的孩子A。如果是小孩,A也应该保留它的父母。

There's an Entity Class "A". Class A might have children of the same type "A". Also "A" should hold it's parent if it is a child.

这可能吗?如果是这样,我应该如何映射Entity类中的关系?
[A有一个id列。]

Is this possible? If so how should I map the relations in the Entity class? ["A" has an id column.]

推荐答案

是的,这是可能的。这是标准双向 @ManyToOne / @OneToMany 关系的特例。这是特殊的,因为关系两端的实体是相同的。一般情况详见 JPA 2.0规范的第2.10.2节。

Yes, this is possible. This is a special case of the standard bidirectional @ManyToOne/@OneToMany relationship. It is special because the entity on each end of the relationship is the same. The general case is detailed in Section 2.10.2 of the JPA 2.0 spec.

这是一个有效的例子。首先,实体类 A

Here's a worked example. First, the entity class A:

@Entity
public class A implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    @ManyToOne
    private A parent;
    @OneToMany(mappedBy="parent")
    private Collection<A> children;

    // Getters, Setters, serialVersionUID, etc...
}

这是一个粗略的 main()方法,它持续存在三个这样的实体:

Here's a rough main() method that persists three such entities:

public static void main(String[] args) {

    EntityManager em = ... // from EntityManagerFactory, injection, etc.

    em.getTransaction().begin();

    A parent   = new A();
    A son      = new A();
    A daughter = new A();

    son.setParent(parent);
    daughter.setParent(parent);
    parent.setChildren(Arrays.asList(son, daughter));

    em.persist(parent);
    em.persist(son);
    em.persist(daughter);

    em.getTransaction().commit();
}

在这种情况下,所有三个实体实例必须在事务提交之前保持不变。如果我未能在父子关系图中保留其中一个实体,则会在 commit()上抛出异常。在Eclipselink上,这是一个 RollbackException 详细说明不一致。

In this case, all three entity instances must be persisted before transaction commit. If I fail to persist one of the entities in the graph of parent-child relationships, then an exception is thrown on commit(). On Eclipselink, this is a RollbackException detailing the inconsistency.

此行为可通过 cascade 属性 A @OneToMany @ ManyToOne 注释。例如,如果我在这两个注释上设置 cascade = CascadeType.ALL ,我可以安全地保留其中一个实体并忽略其他实体。假设我在我的交易中坚持。 JPA实现遍历 parent children 属性,因为它标有 CascadeType.ALL 。 JPA实现在那里找到 son daughter 。然后它代表我坚持这两个孩子,即使我没有明确要求它。

This behavior is configurable through the cascade attribute on A's @OneToMany and @ManyToOne annotations. For instance, if I set cascade=CascadeType.ALL on both of those annotations, I could safely persist one of the entities and ignore the others. Say I persisted parent in my transaction. The JPA implementation traverses parent's children property because it is marked with CascadeType.ALL. The JPA implementation finds son and daughter there. It then persists both children on my behalf, even though I didn't explicitly request it.

还有一个注意事项。程序员始终有责任更新双向关系的双方。换句话说,每当我将一个孩子添加到某个父母时,我必须相应地更新孩子的父母属性。仅更新双向关系的一侧是JPA下的错误。始终更新关系的两个方面。这是在JPA 2.0规范的第42页上明确写出的:

One more note. It is always the programmer's responsibility to update both sides of a bidirectional relationship. In other words, whenever I add a child to some parent, I must update the child's parent property accordingly. Updating only one side of a bidirectional relationship is an error under JPA. Always update both sides of the relationship. This is written unambiguously on page 42 of the JPA 2.0 spec:


请注意,应用程序负责维护运行时的一致性关系 - 例如,当应用程序在运行时更新
关系时,确保双向关系的一和多方彼此一致。

Note that it is the application that bears responsibility for maintaining the consistency of runtime relationships—for example, for insuring that the "one" and the "many" sides of a bidirectional relationship are consistent with one another when the application updates the relationship at runtime.

这篇关于JPA:如何具有相同实体类型的一对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆