Если вы хотите использовать отложенную инициализацию Hibernate / JPA (это нормальный случай), тогда вам не следует не использовать составной шаблон .
Проблема, связанная с Hibernate с Composite Pattern : в Composite у вас есть Composite, у которого есть ссылка на его дочерние Компоненты.
Но Компонент является только абстрактным классом или Интерфейсом, поэтому каждый Компонент является Листом или Композитом.
Если вы теперь используете ленивую инициализацию для набора составных объектов Composite, но затем некоторые, как необходимо привести конкретный дочерний элемент к Leaf или Composite, вы получите исключение Cast, потому что hibernate использует прокси для компонента, который не может быть приведен к Leaf или Composite. Композитный.
Второй недостаток составного шаблона заключается в том, что каждый класс будет листом или составным в течение своего полного жизненного цикла.
Это хорошо, если ваша структура никогда не меняется. Но это не сработает, если лист должен стать составным, потому что кто-то хочет добавить подузел / лист.
Так что, если у вас есть какая-то динамическая структура, я рекомендую один класс Node, который имеет двунаправленную связь между родительским и дочерним узлами.
Отношения должны быть двунаправленными, если вам часто приходится переходить к родителям или детям в вашем коде.
Поддерживать эти отношения немного сложно, поэтому я решил опубликовать еще немного кода.
@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();
}
}