1

次のユースケースがあります。

  • 親には、子と親タグが含まれます。
  • 子には、ChildrenTags とその親ノードが含まれます。
  • ParentTags と ChildrenTags はどちらも、T が親または子であるタグです。

ここで、この親またはその子の 1 つに関連するすべてのタグをマップする 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;

}

Child.class

@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 は機能します (所有者が監査されない限り、そのバグを見つけるのは困難でした)。

私はすでに成功せずに次の解決策を試しました:

@結合式

    @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;
}

例外ではありません。実際にデバッグすると、ローダーが適切なタグをすべて見つけますが、それらでコレクションを初期化しないことがわかります。@Loader と @NamedNativeQuery がうまくいかないことがわかったので、クエリを hbm 構成ファイルに入れようとしましたが、成功しませんでした (ここで何か間違ったことをした可能性があります)。ただし、構成ファイルなしでソリューションを実装したいと思います。

別の列 (owner_id) を追加することもできますが、モデルを変更せずにその問題を解決する方法を見つけることができれば、その方がよいでしょう。

ジェネリックが関係しているかどうかはわかりません。さらに、私のエンティティは監査され、索引付けされています。

どんな助けでも大歓迎です!

4

0 に答える 0