15

JPA 2.0 を使用して、一般的な関係を持つポリモーフィック エンティティを作成しようとしています。イベント テーブルと通知テーブルの 2 つのテーブルが必要です。これらのテーブル内には、次のように、互いに関連する具体的なエンティティがあります。

Event  <---------- Notification<X extends Event>
 |                      |
LoginEvent <------ LoginNotification extends Notification<LoginEvent>

論理的には、これは SQL で可能であるように、休止状態でも可能です。

+----------+    +----------+
| Event    |    | Notif    |
+----------+    +----------+
|          |    | Id       |
| Id       | <- | Evt_id   |
| Type     | <- | Type     |
| ...      |    | ...      |
+----------+    +----------+

これは私が持っているものです:

@Entity
@Inheritance
public abstract class Event{

...
}

@Entity
public class LoginEvent extends Event{

...
}

@Entity
@Inheritance
public abstract class Notification<X extends Event>{

 @ManyToOne(optional=false, targetEntity=Event.class)
 @JoinColumn
 private X event;

...
}

@Entity
public class LoginNotification extends Notification<LoginEvent>{

...
}

このコードを使用すると、任意の Event、Notification、LoginEvent、または NotificationEvent を永続化およびフェッチできますがLoginNotification_.event、JPA 2.0 メタモデル クエリでリレーションを使用しようとすると失敗します。この問題は、同様のことを説明しています。

public static volatile SingularAttribute<NotificationEntity, EventEntity> event;

条件クエリで結合を実行しようとすると、次のエラーが発生します。

EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<LoginNotification> query = cb.createQuery(LoginNotification.class);
Root<LoginNotification> root = query.from(LoginNotification.class);

//  This line complains: Type mismatch: cannot convert from
//  Join<LoginNotification,Event> to Join<LoginNotification,LoginEvent>
Join<LoginNotification, LoginEvent> join = 
root.join(LoginNotification_.event, JoinType.INNER);

メタモデルに新しいSingularAttributeを追加することで、このエラーを回避できますLoginNotification_が、これは実行に失敗します:

public abstract class LoginNotification_ extends Notification_ {

    // Adding this Removes Type mismatch error, but causes run-time error
    public static volatile SingularAttribute<LoginNotification, LoginEvent> event; 

    ...
}

いくつかの投稿によると、一般的な関係は機能しません (一般的なインターフェイスへのポインターの JPA 注釈を処理する方法) が、@ManyToOne(optional=false, targetEntity=Event.class)注釈を使用することでそれらを動作させることができます。残念ながら、ジェネリックは JPA 基準クエリを壊しているようです。

このルックアップを実行する方法について何か提案はありますか? コードでは使用できますが、JPA メタモデル結合でLoginNotification.getEvent()は使用できません。LoginNotification_.eventこれを達成するためにジェネリックを使用する代わりに何ができますか?

@Pascal Thivent - これに答えてもらえますか?

4

2 に答える 2

8

これに対する1つの解決策は、「join」関数の使用を避け、代わりに完全なクロス結合を実行することです。

EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<LoginNotification> query = cb.createQuery(LoginNotification.class);
Root<LoginNotification> notfRoot = query.from(LoginNotification.class);
Root<LoginEvent> eventRoot = query.from(LoginEvent.class);
...
query.where(cb.equals(notfRoot.get(Notification_.event), eventRoot.get(Event_.id)), ...(other criteria));

まともなクエリオプティマイザはこれを簡単に処理する必要があると思いますが、このアプローチの効率について誰かが洞察を持っているなら、私はそれを聞きたがっています!

于 2011-01-03T04:56:29.893 に答える