@OneToMany с @JoinFormula с использованием полиморфизма и общего
У меня есть следующий вариант использования:
- Родители содержат Дети и Родительские Теги.
- Дети содержат ChildrenTags и их родительский узел.
- Теги ParentTag и ChildrenTag являются тегами, где T является родительским или дочерним тегами.
Теперь я хочу получить производное поле в Parent, которое отображает все теги относительно этого родителя или одного из его дочерних элементов. SQL-запрос прост, но я не могу заставить его работать, аннотируя данное свойство. Обратите внимание, что отображение @ManyToOne работает как шарм, чтобы найти владельца Parent для тега, см. Мой код ниже (это отношение @OneToMany, тег, возможно, не лучшее имя, которое я мог найти для этого примера).
Parent.class
@Entity
@Audited
public class Parent {
@Id
private Long id;
@OneToMany(mappedBy = "parent")
private List<Child> children;
@OneToMany(mappedBy = "parent")
private List<ParentTag> tags;
// Does not work!
@OneToMany(mappedBy = "owner")
private List<Tag<?>> allTags;
}
Child.class
@Entity
@Audited
public class Child {
@Id
private Long id;
@ManyToOne
private Parent parent;
@OneToMany(mappedBy = "child")
private List<ChildTag> tags;
}
Tag.class
@Entity
@Audited
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Tag<T> {
@Id
private Long id;
protected String value;
@NotAudited // otherwise ClassCastException
@ManyToOne
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(formula = @JoinFormula(
value = "CASE WHEN parent_id IS NOT NULL THEN parent_id WHEN child_id IS NOT NULL THEN (SELECT child.parent_id FROM Child child WHERE child.id = child_id) end",
referencedColumnName="id"))
})
private Parent owner;
public abstract T getNode();
}
ChildTag.class
@Audited
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class ChildTag extends Tag<Child> {
@ManyToOne
private Child child;
@Override
public Child getNode() {
return child;
}
}
ParentTag.class
@Audited
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class ParentTag extends Tag<Parent> {
@ManyToOne
private Parent parent;
@Override
public Parent getNode() {
return parent;
}
}
Я хотел бы найти способ загрузить все теги по заданному запросу или формуле. Обратное отображение @ManyToOne работает (пока владелец не проверен, эту ошибку было трудно найти).
Я уже попробовал следующие решения без успеха:
@JoinFormula
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(formula = @JoinFormula(
value = "CASE WHEN parent_id IS NOT NULL THEN parent_id WHEN child_id IS NOT NULL THEN (SELECT child.parent_id FROM Child child WHERE child.id = child_id) end",
referencedColumnName="id"))
})
private List<Tag<?>> allTags;
Я получаю ClassCastException, формула не может быть приведена в столбец
@Loader
@Entity
@Audited
@NamedNativeQuery(name = "loadAllTags",
query = "SELECT * FROM Tag tag WHERE "
+ "(tag.parent_id IS NOT NULL AND tag.parent_id = :id) OR "
+ "(tag.child_id IS NOT NULL AND EXISTS (SELECT 1 FROM Child child WHERE child.id = tag.child_id AND child.parent_id = :id))")
public class Parent {
...
@Loader(namedQuery = "loadAllTags")
private List<Tag<?>> allTags;
}
Не исключение, на самом деле при отладке я вижу, что загрузчик находит все соответствующие теги, но не инициализирует коллекцию с ними. Я также попытался поместить запрос в конфигурационный файл hbm, так как понял, что @Loader и @NamedNativeQuery не ладят, но безуспешно (возможно, я здесь что-то не так сделал). Однако я бы предпочел реализовать решение без файла конфигурации.
Я мог бы добавить еще один столбец (owner_id), но если бы я мог найти способ решить эту проблему без изменения модели, было бы лучше.
Я не знаю, имеют ли дженерики какое-то отношение к этому. Кроме того, мои объекты проверяются и индексируются.
Любая помощь будет оценена!