我有以下用例:
- 父项包含子项和 ParentTags。
- 子项包含 ChildrenTags 及其父节点。
- ParentTags 和 ChildrenTags 都是 T 为 Parent 或 Child 的标签。
现在我想在 Parent 中创建一个派生字段,将所有标签映射到这个父级或它的一个子级。SQL 查询很简单,但我无法通过注释给定属性来使其工作。请注意,@ManyToOne 映射的作用就像一个魅力,以便找到标签的父所有者,请参阅下面的代码(这是 @OneToMany 关系,标签可能不是我能找到的最佳名称)。
父类
@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;
}
子类
@Entity
@Audited
public class Child {
@Id
private Long id;
@ManyToOne
private Parent parent;
@OneToMany(mappedBy = "child")
private List<ChildTag> tags;
}
标记类
@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;
}
}
我想找到一种通过给定查询或公式加载 allTags 的方法。逆映射@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,无法将公式转换为列
@加载器
@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),但如果我能找到一种方法来解决这个问题而不改变模型,那就更好了。
我不知道泛型是否与它有关。此外,我的实体经过审计和索引。
任何帮助将不胜感激!