簡體   English   中英

如何使用泛型關系實現多態JPA實體

[英]How to implement polymorphic JPA entities with generic relations

我正在嘗試使用JPA 2.0來創建具有泛型關系的多態實體。 應該有兩個表,一個事件表和一個通知表。 在這些表中是彼此相關的具體實體,如下所示:

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

邏輯上這應該可以在hibernate中實現,因為它可以在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,但是當我嘗試在JPA 2.0元模型查詢中使用LoginNotification_.event關系時,它就會失敗。 這個問題解釋了類似的東西

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);

我可以通過向LoginNotification_元模型添加新的SingularAttribute來解決此錯誤,但是執行失敗:

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標准查詢。

有關如何執行此查找的建議嗎? 我可以在我的代碼中使用LoginNotification.getEvent() ,但我不能在我的JPA元模型連接中使用LoginNotification_.event 使用泛型來實現這一目標的替代方法是什么?

@Pascal Thivent - 你能回答這個問題嗎?

對此的一個解決方案是避免使用“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));

我認為一個體面的查詢優化器應該對此做一些簡短的工作,但如果有人對這種方法的效率有任何見解,我會熱衷於聽到它!

我試過你的泛型代碼,@ logan。

但我終於發現最簡單的方法是讓T實現Serializable

@Entity
public class IgsSubject extends BasicObject implements Serializable{

    private static final long serialVersionUID = -5387429446192609471L;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM