如何实现具有通用关系的多态 JPA 实体
我正在尝试使用 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>{
...
}
使用此代码,我可以持久保存并获取任何事件、通知、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 - 你能回答这个问题吗?
I'm trying to use JPA 2.0 to create polymorphic entities with generic relations. There should be two tables, an event table and a notification table. Inside those table are concrete entities that are related to one another, like so:
Event <---------- Notification<X extends Event>
| |
LoginEvent <------ LoginNotification extends Notification<LoginEvent>
Logically this should be possible in hibernate, as it is possible in SQL:
+----------+ +----------+
| Event | | Notif |
+----------+ +----------+
| | | Id |
| Id | <- | Evt_id |
| Type | <- | Type |
| ... | | ... |
+----------+ +----------+
This is what I have:
@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>{
...
}
Using this code, I can persist and fetch any Event, Notification, LoginEvent, or NotificationEvent, but it falls down when I try to use the LoginNotification_.event
relation in my JPA 2.0 metamodel queries. This issue explains something similar.
public static volatile SingularAttribute<NotificationEntity, EventEntity> event;
When I try to do a join in a criteria query, I get an error:
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);
I can get around this error, by adding a new SingularAttribute
to the LoginNotification_
metamodel, but this fails in execution:
public abstract class LoginNotification_ extends Notification_ {
// Adding this Removes Type mismatch error, but causes run-time error
public static volatile SingularAttribute<LoginNotification, LoginEvent> event;
...
}
According to some posts, generic relations won't work (How to handle JPA annotations for a pointer to a generic interface), but by using a @ManyToOne(optional=false, targetEntity=Event.class)
annotation, we can get them to behave. Unfortunately, the generics seem to break the JPA criteria query.
Are there any suggestions on how I can perform this lookup? I can use LoginNotification.getEvent()
in my code, but I cannot use LoginNotification_.event
in my JPA metamodel joins. What's the alternative to using generics to accomplish this?
@Pascal Thivent - Can you answer this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决这个问题的一个解决方案是避免使用“join”函数并进行完整的交叉联接:
我认为一个像样的查询优化器应该可以轻松完成此任务,但如果有人对这种方法的效率有任何见解,我会一定要听听!
One solution to this is to avoid using the 'join' function and do a full cross join instead:
I would assume that a decent query optimizer should make short work of this, but if anyone has any insight on the efficiency of this approach I would be keen to hear it!
我已经尝试过您的通用代码 @logan 。
但我最终发现最简单的方法是让
T
实现Serialized
I've tried you code for generic, @logan .
But I finally found the simplest way is let
T
implementsSerializable