Nếu bạn muốn sử dụng khởi tạo lười biếng Hibernate/JPA (trường hợp bình thường) thì bạn nên không sử dụng mẫu tổng hợp.
Vấn đề liên quan đến Hibernate với Composite Pattern là: trong một Composite, bạn có một Composite có tham chiếu thành phần con của nó. Nhưng Component chỉ là một lớp trừu tượng hoặc Interface, vì vậy mỗi Component là một Leaf hoặc một Composite. Nếu bây giờ bạn sử dụng khởi tạo lười cho tập hợp Composite, nhưng sau đó một số cách cần đưa một con cụ thể vào Leaf hoặc Composite, bạn sẽ nhận được một ngoại lệ Cast vì hibernate sử dụng proxy cho thành phần không thể được đưa vào Leaf hoặc Composite.
Hạn chế thứ hai của mẫu hỗn hợp là mọi lớp sẽ là Lá hoặc Hỗn hợp cho toàn bộ thời gian tồn tại của nó. Điều đó là tốt nếu cấu trúc của bạn không bao giờ thay đổi. Nhưng nó sẽ không hoạt động nếu Leaf phải trở thành một Composite vì ai đó muốn thêm một nút con/lá.
Vì vậy, nếu bạn có cấu trúc động, tôi đề xuất một lớp Nút có mối quan hệ hai chiều giữa nút cha và nút con. Mối quan hệ phải là hai chiều nếu bạn thường cần điều hướng đến cha mẹ hoặc trẻ em trong mã của bạn. Duy trì mối quan hệ đó là một chút phức tạp, vì vậy tôi quyết định đăng thêm một số mã.
@Entity
public class Domain {
@Id
private long id;
/** The parent domain, can be null if this is the root domain. */
@ManyToOne
private Domain parent;
/**
* The children domain of this domain.
*
* This is the inverse side of the parent relation.
*
* <strong>It is the children responsibility to manage there parents children set!</strong>
*/
@NotNull
@OneToMany(mappedBy = "parent")
private Set<Domain> children = new HashSet<Domain>();
/**
* Do not use this Constructor!
* Used only by Hibernate.
*/
Domain() {
}
/**
* Instantiates a new domain.
* The domain will be of the same state like the parent domain.
*
* @param parent the parent domain
* @see Domain#createRoot()
*/
public Domain(final Domain parent) {
if(parent==null) throw new IllegalArgumentException("parent required");
this.parent = parent;
registerInParentsChilds();
}
/** Register this domain in the child list of its parent. */
private void registerInParentsChilds() {
this.parent.children.add(this);
}
/**
* Return the <strong>unmodifiable</strong> children of this domain.
*
* @return the child nodes.
*/
public Set<Domain> getChildren() {
return Collections.unmodifiableSet(this.children);
}
/**
* Move this domain to an new parent domain.
*
* @param newParent the new parent
*/
public void move(final Domain newParent) {
Check.notNullArgument(newParent, "newParent");
if (!isProperMoveTarget(newParent) /* detect circles... */) {
throw new IllegalArgumentException("move", "not a proper new parent", this);
}
this.parent.children.remove(this);
this.parent = newParent;
registerInParentsChilds();
}
/**
* Creates the root.
*
* @param bid the bid
* @return the domain
*/
public static Domain createRoot() {
return new Domain();
}
}
Tốt, ngắn và chính xác. –
Tôi sẽ không khuyên bạn nên sử dụng Danh sách. Hibernate không thể đồng thời lấy nhiều túi (danh sách). Nếu bạn cố gắng tải 3 cấp độ của cây này trong cùng một truy vấn, bạn sẽ cần phải sử dụng Đặt thay thế. – Dherik
@Dherik bạn nói đúng. Sử dụng một danh sách nên có thể với một chỉ mục mặc dù. – Thomas