我正在尝试使用JPA 2.0创建具有通用关系的多态实体。应该有两个表,一个事件表和一个通知表。在这些表内是彼此相关的具体实体,如下所示:
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元模型查询中使用该关系时,它就会崩溃。此问题解释了类似的问题。
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);
我可以通过向元模型添加新的方法SingularAttribute来解决此错误LoginNotification_,但是执行失败:
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标准查询。
@ManyToOne(optional=false, targetEntity=Event.class)
关于如何执行此查找有什么建议吗?我可以LoginNotification.getEvent()在代码中使用,但不能LoginNotification_.event在JPA元模型联接中使用。使用泛型来完成此任务的替代方法是什么?
LoginNotification.getEvent()
@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));
我认为一个不错的查询优化器应该做的简短,但是如果有人对这种方法的效率有任何见识,我将很乐意听到!