2011-01-02 9 views
14

Próbuję użyć JPA 2.0 do tworzenia polimorficznych obiektów o ogólnych relacjach. Powinny istnieć dwie tabele, tabela zdarzeń i tabela powiadomień. Wewnątrz tych tabeli są konkretne podmioty, które są powiązane ze sobą, tak jak:Jak wdrożyć polimorficzne jednostki WZP o ogólnych relacjach

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

Logicznie powinno to być możliwe w hibernacji, jak to jest możliwe w SQL:

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

To jest to, co mam :

@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>{ 

... 
} 

Za pomocą tego kodu, mogę utrzymywać i pobrać żadnych zdarzeń, powiadomień, LoginEvent lub NotificationEvent, ale spada gdy próbuję użyć LoginNotification_.event relację w moich kwerendach metamodelu JPA 2.0. This issue wyjaśnia coś podobnego.

public static volatile SingularAttribute<NotificationEntity, EventEntity> event; 

Kiedy próbuję zrobić sprzężenia w zapytaniu kryteria, pojawia się błąd:

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

mogę obejść ten problem, dodając nowy SingularAttribute do LoginNotification_ metamodelu, ale ten nie w wykonaniu:

public abstract class LoginNotification_ extends Notification_ { 

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

    ... 
} 

według niektórych stanowisk, relacje rodzajowe nie będą działać (How to handle JPA annotations for a pointer to a generic interface), ale przy użyciu @ManyToOne(optional=false, targetEntity=Event.class) się notacja, możemy sprawić, żeby się zachowali. Niestety, generics wydają się przełamać zapytanie o kryteria JPA.

Czy są jakieś sugestie, w jaki sposób mogę wykonać to wyszukiwanie? W moim kodzie mogę używać LoginNotification.getEvent(), ale nie mogę używać LoginNotification_.event w moich połączeniach metamodelu JPA. Jaka jest alternatywa dla zastosowania generycznych w celu osiągnięcia tego?

@Pascal Thivent - Czy możesz odpowiedzieć na to pytanie?

Odpowiedz

8

Jednym z rozwiązań tego problemu jest unikanie korzystania z funkcji „przyłączyć” i zrobić pełny przekrój dołączyć zamiast:

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

Przypuszczam, że to przyzwoity optymalizator kwerendy należy zrobić krótką pracę, ale jeśli ktoś ma jakiś wgląd w skuteczność tego podejścia, chciałbym to usłyszeć!

+0

Doskonałe, kiedyś napisać dołączy w ten sposób w SQL tak. – logan

0

Próbowałem już kodu ogólnego, @logan.

Ale w końcu znalazłem najprostszym sposobem jest niech T realizuje Serializable

@Entity 
public class IgsSubject extends BasicObject implements Serializable{ 

    private static final long serialVersionUID = -5387429446192609471L; 
Powiązane problemy