2011-01-02 37 views
14

Tôi đang cố gắng sử dụng JPA 2.0 để tạo các thực thể đa hình với các quan hệ chung. Nên có hai bảng, một bảng sự kiện và một bảng thông báo. Bên trong những bảng là các đơn vị cụ thể có liên quan đến nhau, như vậy:Cách thực hiện các thực thể JPA đa hình với các quan hệ chung

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

Logic này nên có thể trong chế độ ngủ đông, vì nó có thể trong SQL:

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

Đây là những gì tôi có :

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

... 
} 

sử dụng mã này, tôi có thể tồn tại và lấy bất kỳ tổ chức sự kiện, thông báo, LoginEvent, hoặc NotificationEvent, nhưng nó rơi xuống khi tôi cố gắng sử dụng các mối quan hệ LoginNotification_.event trong các truy vấn metamodel JPA 2.0 của tôi. This issue giải thích điều tương tự.

public static volatile SingularAttribute<NotificationEntity, EventEntity> event; 

Khi tôi cố gắng để làm một tham gia trong một truy vấn tiêu chí, tôi nhận được một lỗi:

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

tôi có thể khắc phục lỗi này, bằng cách thêm một mới SingularAttribute đến LoginNotification_ metamodel, nhưng điều này thất bại trong thực hiện:

public abstract class LoginNotification_ extends Notification_ { 

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

    ... 
} 

theo một số bài viết, quan hệ chung chung sẽ không hoạt động (How to handle JPA annotations for a pointer to a generic interface), nhưng bằng cách sử dụng một @ManyToOne(optional=false, targetEntity=Event.class) một ký hiệu, chúng ta có thể khiến chúng cư xử. Thật không may, các generics dường như phá vỡ các truy vấn tiêu chuẩn JPA.

Có bất kỳ đề xuất nào về cách tôi có thể thực hiện tra cứu này không? Tôi có thể sử dụng LoginNotification.getEvent() trong mã của mình, nhưng tôi không thể sử dụng LoginNotification_.event trong tham gia metamodel JPA của tôi. Có gì thay thế để sử dụng Generics để thực hiện điều này?

@Pascal Thivent - Bạn có thể trả lời câu hỏi này không?

Trả lời

8

Một giải pháp này là để tránh sử dụng 'tham gia' chức năng và làm một cây thánh giá đầy đủ tham gia thay vì:

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

tôi sẽ giả định rằng một truy vấn tối ưu đàng hoàng nên làm cho công việc ngắn này, nhưng nếu có ai có bất kỳ cái nhìn sâu sắc về hiệu quả của cách tiếp cận này tôi sẽ được quan tâm để nghe nó!

+0

Tuyệt vời, tôi sử dụng để viết tham gia của tôi theo cách này trong SQL anyway. – logan

0

Tôi đã thử bạn viết mã cho chung, @logan.

Nhưng cuối cùng tôi đã tìm thấy cách đơn giản nhất là hãy T thực hiện Serializable

@Entity 
public class IgsSubject extends BasicObject implements Serializable{ 

    private static final long serialVersionUID = -5387429446192609471L; 
Các vấn đề liên quan