如何使用generics关系实现多态JPA实体
我正在尝试使用JPA 2.0来创建具有generics关系的多态实体。 应该有两个表,一个事件表和一个通知表。 在这些表中是彼此相关的具体实体,如下所示:
Event <---------- Notification | | LoginEvent <------ LoginNotification extends Notification
从逻辑上讲,这应该可以在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{ @ManyToOne(optional=false, targetEntity=Event.class) @JoinColumn private X event; ... } @Entity public class LoginNotification extends Notification{ ... }
使用此代码,我可以持久化并获取任何Event,Notification,LoginEvent或NotificationEvent,但是当我尝试在JPA 2.0元模型查询中使用LoginNotification_.event
关系时,它就会失败。 这个问题解释了类似的东西
public static volatile SingularAttribute event;
当我尝试在条件查询中进行连接时,出现错误:
EntityManager em = getEntityManager(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery query = cb.createQuery(LoginNotification.class); Root root = query.from(LoginNotification.class); // This line complains: Type mismatch: cannot convert from // Join to Join Join 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 event; ... }
根据一些post,generics关系不起作用( 如何处理指向generics接口的指针的JPA注释 ),但是通过使用@ManyToOne(optional=false, targetEntity=Event.class)
注释,我们可以将它们带到表现。 不幸的是,generics似乎打破了JPA标准查询。
有关如何执行此查找的建议吗? 我可以在我的代码中使用LoginNotification.getEvent()
,但我不能在我的JPA元模型联接中使用LoginNotification_.event
。 使用generics来实现这一目标的替代方法是什么?
@Pascal Thivent – 你能回答这个问题吗?
一个解决方案是避免使用’join’函数并执行完全交叉连接:
EntityManager em = getEntityManager(); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery query = cb.createQuery(LoginNotification.class); Root notfRoot = query.from(LoginNotification.class); Root eventRoot = query.from(LoginEvent.class); ... query.where(cb.equals(notfRoot.get(Notification_.event), eventRoot.get(Event_.id)), ...(other criteria));
我认为一个体面的查询优化器应该对此做一些简短的工作,但如果有人对这种方法的效率有任何见解,我会热衷于听到它!
我试过你的generics代码,@ logan。
但我终于发现最简单的方法是让T
实现Serializable
@Entity public class IgsSubject extends BasicObject implements Serializable{ private static final long serialVersionUID = -5387429446192609471L;