有一个实体类“ A”。A类可能具有相同类型“ A”的子级。如果“ A”是孩子,则也应保留它的父母。
这可能吗?如果是这样,我应该如何在Entity类中映射关系?[“ A”有一个id列。]
是的,这是可能的。这是标准双向@ManyToOne/ @OneToMany关系的特例。之所以特别是因为关系两端的实体都是相同的。JPA 2.0规范的第2.10.2节详细介绍了一般情况。
这是一个可行的示例。首先,实体类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()可保留三个此类实体的粗略方法:
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详细说明不一致的地方。
commit(
RollbackException
此行为是通过可配置cascade的属性A的@OneToMany和@ManyToOne注释。例如,如果我同时设置cascade=CascadeType.ALL了这两个注释,则可以安全地保留其中一个实体,而忽略其他实体。说我坚持parent进行交易。JPA实现遍历parent的children属性是因为它用标记CascadeType.ALL。JPA实现的发现son和daughter那里。然后,即使我没有明确要求,它也代表我保留了两个孩子。
cascade
@OneToMany
@ManyToOne
cascade=CascadeType.ALL
parent
children
CascadeType.ALL
daughter
还有一点。更新双向关系的双方始终是程序员的责任。换句话说,每当我将孩子添加到某个父母中时,都必须相应地更新孩子的parent属性。在JPA下,仅更新双向关系的一侧是错误。始终更新关系的双方。这是明确写在JPA 2.0规范的第42页上的:
请注意,应用程序负责维护运行时关系的一致性,例如,当应用程序在运行时更新关系时,确保双向关系的“一侧”和“许多”侧彼此一致。