使用带有3层结构的@IdClass,在主键中使用复合键进行Hibernate映射
作者:互联网
实际上我的唯一(从我发现的有意义的)差异是我使用@IdClass并且我很可能无法切换到与hibernate不同的提供者.
但无论如何这里是代码(删除不重要的部分):
PermissionContextType.java:
@Entity
@IdClass(PermissionContextTypePk.class)
public class PermissionContextType{
@Id
private String id;
@Id
@JoinColumn (name = "PROJECT", referencedColumnName = "ID")
@ManyToOne ()
private Project project;
public static class PermissionContextTypePk implements Serializable{
public String project;
public String id;
// ... eq and hashCode here ...
}
}
PermissionContext.java:
@Entity
@IdClass(PermissionContextPk.class)
public class PermissionContext{
@Id
private String id;
@Id
@JoinColumns ({
@JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT"),
@JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "ID")
})
@ManyToOne
private PermissionContextType permissionContextType;
public static class PermissionContextPk implements Serializable{
public String id;
public PermissionContextTypePk permissionContextType;
// ... eq and hashCode here ...
}
}
Permission.java:
@Entity
@IdClass(PermissionPk.class)
public class Permission{
@Id
private String id;
@Id
@JoinColumns ({
@JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT"),
@JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "PERMISSIONCONTEXTTYPE"),
@JoinColumn (name = "PERMISSIONCONTEXT", referencedColumnName = "ID")
})
@ManyToOne
private PermissionContext permissionContext;
public static class PermissionPk implements Serializable{
public String id;
public PermissionContextPk permissionContext;
// ... eq and hashCode here ...
}
}
而我得到的是:
org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: PermissionContext
Caused by: org.hibernate.AssertionFailure: org.hibernate.AssertionFailure: Unexpected nested component on the referenced entity when mapping a @MapsId: PermissionContext
有没有人知道这是一个hibernate错误,我应该将它发布在他们的问题跟踪系统上(并祈祷我能够更新到给定的hibernate版本)或者我的绑定实体的方式是否存在根本错误?
我已经使用EAP 6.1(4.2.0)上的hibernate实现以及wildfly(不知道哪一个)进行了检查.
解决方法:
好的,所以这是我到目前为止所发现的:
谢谢我的朋友:https://hibernate.atlassian.net/browse/HHH-5764,这很可能是这种行为的原因.
我发现了一个解决方法:
Permission.java:
@Entity
@IdClass(PermissionPk.class)
public class Permission{
@Id
private String id;
// for the next 3 fields there are no public acessors, so the public API of the class was not changed !
@Id
@Column(name = "PROJECT")
private String projectId;
@Id
@Column(name = "PERMISSIONCONTEXTTYPE")
private String permissionContextTypeId;
@Id
@Column(name = "PERMISSIONCONTEXT")
private String permissionContextId;
@JoinColumns ({
@JoinColumn (name = "PROJECT", referencedColumnName = "PROJECT", updatable = false, insertable = false),
@JoinColumn (name = "PERMISSIONCONTEXTTYPE", referencedColumnName = "PERMISSIONCONTEXTTYPE", updatable = false, insertable = false),
@JoinColumn (name = "PERMISSIONCONTEXT", referencedColumnName = "ID", updatable = false, insertable = false)
})
@ManyToOne
private PermissionContext permissionContext;
public static class PermissionPk implements Serializable{
// previously they where private as well, but removed public constructor for the sake of simplicity of the question - so no changes where necesary in public API of the class !
private String id;
private String projectId;
private String permissionContextTypeId;
private String permissionContextId;
public PermissionPk () {}
public PermissionPk (String aId, PermissionContextPk aPermissionContext) {
this.id = aId;
permissionContextId = aPermissionContext.id;
permissionContextTypeId = aPermissionContext.permissionContextType.id;
projectId = aPermissionContext.permissionContextType.project;
}
... eq and hashCode here ...
}
}
这种解决方法的好处是它不会以任何方式更改类的公共API
(唯一的变化是我需要在Perk中显示Pk的上下文和上下文类型的字段 – 它们之前只有一个公共构造函数的私有[但是再次简化了问题]),也没有改变jpql查询,同时解决方法是可扩展的(对任何层数 – 只要每个偶数pk不包含另一个pk),所以如果错误将被解决,将很容易删除变通方法.
我仍然乐意接受对我的解决方法或问题本身的任何评论.
标签:java,jpa,hibernate,java-ee-6 来源: https://codeday.me/bug/20190708/1403548.html