SINGLE_TABLE 戦略を使用した JPA エンティティの継承に関する問題。getter @Discriminator では、継承の範囲を縮小します。
私は次の構造を持っています:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type")
@DiscriminatorValue("A")
class A {
...
}
@Entity
@DiscriminatorValue("B")
class B extends A {
...
}
@Entity
@DiscriminatorValue("C")
class C extends B {
...
}
@Entity
class Something{
@ManyToMany // blah blah
private List<B> listB; // getters and setters
}
問題は次のとおりです。クラス C のオブジェクトがあります (継承 C も B であると仮定します)。私がやっているとき:
Something s = Something.findById(11); // Here is listB with elements of type C and B
List<B> listB = s.getListB();
クラス B のオブジェクトのみをフェッチし、C はフェッチしません。ただし、C は B を拡張するため、リストにも含まれている必要があります。Getter は次のようなクエリを作成します。
SELECT t1.id, t1.type, t1.sys_modified_date, t1.sys_created_date, t1.name, t1.shortName
FROM something_b t0 INNER JOIN A t1 ON t0.listB = t1.id
WHERE t0.news = ? AND t1.type = ?
[params=(long) 205, (String) B]
問題は、このゲッター (Something.getListB) がこのリストを (ディスクリミネーター B によって) クラス B のみに縮小することです。この結果、オブジェクト クラス C はリストにありません。厳密な型「t1.type = B」を示す @Discriminator が原因です。「t1.type IN (B,C)」のようなセット/リストをそこに置くことはできません。
カスタム JPQL クエリは、さまざまな方法で構築されます。
SELECT t1.id, t1.type, t1.sys_modified_date, t1.sys_created_date, t1.name, t1.shortName
FROM something_b t0 INNER JOIN A t1 ON t0.listB = t1.id
WHERE t0.news = ? AND t1.type IN (?, ?)
[params=(long) 205, (String) B, (String) C]
そして彼らは彼らがすべきように働きます。しかし、ゲッターはどうですか?
興味深いのは、Something クラスを B クラスから A クラス (すべてのベース) に変更すると、次のようになるという事実です。// ゲッターとセッター }
これは問題を解決します。クエリのゲッターで:
SELECT t1.id, t1.type, t1.sys_modified_date, t1.sys_created_date, t1.name, t1.shortName
FROM something_b t0 INNER JOIN A t1 ON t0.listB = t1.id
WHERE t0.news = ?
[params=(long) 205]
「AND t1.type = ?」が消えます。動作しますが、「現実世界のオブジェクト」から「ORM エンティティ」へのマッピングを妨げます。その解決策は変化し、その抽象化を悪化させます。それはエレガントな解決策ではありません。
質問:
どうすればこの問題を解決できますか?
getter でカスタム JPQL クエリを使用できますか?
そのゲッターに B および C オブジェクトを取得させる方法は?
リストをリストに変更する代わりに、別の提案はありますか???