JPA: 동일한 엔티티 유형의 일대다 관계를 갖는 방법
엔티티 클래스 A가 있습니다.클래스 A에는, 같은 타입의 「A」의 아이가 있는 경우가 있습니다.또한 "A"는 자녀일 경우 부모를 보유해야 합니다.
이게 가능합니까?이 경우 엔티티 클래스의 관계를 어떻게 매핑해야 합니까?['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()이러한 3개의 엔티티를 유지하는 방법:
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();
}
이 경우 트랜잭션 커밋 전에 3개의 엔티티 인스턴스를 모두 유지해야 합니다.부모-자녀 관계 그래프에서 엔티티 중 하나를 유지하지 못하면 예외가 발생합니다.commit()Eclipselink에서 이거는RollbackException상세하게 기재되어 있습니다.
이 동작은, 를 개입시켜 설정할 수 있습니다.cascade탓으로 돌리다A의@OneToMany그리고.@ManyToOne주석입니다.예를 들어, 제가cascade=CascadeType.ALL두 개의 주석 모두, 나는 안전하게 하나의 엔티티를 유지하고 다른 엔티티를 무시할 수 있었다.내가 끈질겼다고 해parent제 거래에서요.JPA 구현이 통과합니다.parent의children마크되어 있는 특성CascadeType.ALLJPA의 실장에서는,son그리고.daughter제가 명시적으로 요청하지 않았음에도 불구하고 저를 대신해서 두 아이를 지속시킵니다.
한 장 더.쌍방향 관계의 양쪽을 갱신하는 것은 항상 프로그래머의 책임입니다.즉, 어떤 부모에 아이를 추가할 때마다 그에 따라 아이의 부모 속성을 업데이트해야 합니다.쌍방향 관계의 한쪽만 갱신하는 것은 JPA에서는 에러입니다.항상 양쪽 관계를 업데이트하십시오.이것은 JPA 2.0 사양의 42페이지에 명확하게 기재되어 있습니다.
런타임 관계의 일관성을 유지할 책임이 있는 것은 응용 프로그램입니다. 예를 들어, 응용 프로그램이 런타임에 관계를 업데이트할 때 쌍방향 관계의 "하나"와 "다수"가 서로 일관성을 유지하도록 보장하는 것입니다.
나에게는 다대다 관계를 이용하는 것이 요령이었다.엔티티 A가 하위 분할을 가질 수 있는 분할이라고 가정합니다.그런 다음(관련 없는 세부 정보를 건너뜁니다):
@Entity
@Table(name = "DIVISION")
@EntityListeners( { HierarchyListener.class })
public class Division implements IHierarchyElement {
private Long id;
@Id
@Column(name = "DIV_ID")
public Long getId() {
return id;
}
...
private Division parent;
private List<Division> subDivisions = new ArrayList<Division>();
...
@ManyToOne
@JoinColumn(name = "DIV_PARENT_ID")
public Division getParent() {
return parent;
}
@ManyToMany
@JoinTable(name = "DIVISION", joinColumns = { @JoinColumn(name = "DIV_PARENT_ID") }, inverseJoinColumns = { @JoinColumn(name = "DIV_ID") })
public List<Division> getSubDivisions() {
return subDivisions;
}
...
}
에 관한 JPA에 근거한)는 그것을 약하기 에 인터페이스를 했습니다.IHierarchyElement 리스너 " " " "HierarchyListener:
public interface IHierarchyElement {
public String getNodeId();
public IHierarchyElement getParent();
public Short getLevel();
public void setLevel(Short level);
public IHierarchyElement getTop();
public void setTop(IHierarchyElement top);
public String getTreePath();
public void setTreePath(String theTreePath);
}
public class HierarchyListener {
@PrePersist
@PreUpdate
public void setHierarchyAttributes(IHierarchyElement entity) {
final IHierarchyElement parent = entity.getParent();
// set level
if (parent == null) {
entity.setLevel((short) 0);
} else {
if (parent.getLevel() == null) {
throw new PersistenceException("Parent entity must have level defined");
}
if (parent.getLevel() == Short.MAX_VALUE) {
throw new PersistenceException("Maximum number of hierarchy levels reached - please restrict use of parent/level relationship for "
+ entity.getClass());
}
entity.setLevel(Short.valueOf((short) (parent.getLevel().intValue() + 1)));
}
// set top
if (parent == null) {
entity.setTop(entity);
} else {
if (parent.getTop() == null) {
throw new PersistenceException("Parent entity must have top defined");
}
entity.setTop(parent.getTop());
}
// set tree path
try {
if (parent != null) {
String parentTreePath = StringUtils.isNotBlank(parent.getTreePath()) ? parent.getTreePath() : "";
entity.setTreePath(parentTreePath + parent.getNodeId() + ".");
} else {
entity.setTreePath(null);
}
} catch (UnsupportedOperationException uoe) {
LOGGER.warn(uoe);
}
}
}
언급URL : https://stackoverflow.com/questions/3393515/jpa-how-to-have-one-to-many-relation-of-the-same-entity-type
'programing' 카테고리의 다른 글
| Composer에서 패키지를 전체적으로 제거하려면 어떻게 해야 합니까? (0) | 2023.01.06 |
|---|---|
| guava와 apache 등가 라이브러리의 큰 개선점은 무엇입니까? (0) | 2023.01.06 |
| C에서 문자 배열의 첫 번째 요소로 \0을 정의하는 이유는 무엇입니까? (0) | 2023.01.06 |
| HTTP를 통한 리모트서버로부터의 이미지 복사 (0) | 2023.01.06 |
| 스위치 라벨의 기본 색상을 vuetify로 변경 또는 덮어쓰려면 어떻게 해야 합니까? (0) | 2023.01.06 |