Hibernate EclipseLink:多列、一对一、JPA 2.0@EmbeddedId使用@MapsId失败,@JoinColumn上为只读(比较派生标识)
我的设计如下:Hibernate EclipseLink:多列、一对一、JPA 2.0@EmbeddedId使用@MapsId失败,@JoinColumn上为只读(比较派生标识),hibernate,jpa,mapping,jpa-2.0,eclipselink,Hibernate,Jpa,Mapping,Jpa 2.0,Eclipselink,我的设计如下: (来源:) 简单逻辑:Foos使用多列PK来使用相同的列(相同的键)发布地址 以下是JPA 2.0@EmbeddedId的映射(使用FooId中的嵌套ID类PostAddressId和Foo中的@MapsId注释映射到它): 堆栈跟踪: Exception [EclipseLink-46] (Eclipse Persistence Services - 2.3.0.v20110429-r9282): org.eclipse.persistence.exceptions.Desc
(来源:) 简单逻辑:Foos使用多列PK来使用相同的列(相同的键)发布地址 以下是JPA 2.0@EmbeddedId的映射(使用FooId中的嵌套ID类PostAddressId和Foo中的@MapsId注释映射到它): 堆栈跟踪:
Exception [EclipseLink-46] (Eclipse Persistence Services - 2.3.0.v20110429-r9282): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: There should be one non-read-only mapping defined for the primary key field [Foos.ordinal_nbr].
Descriptor: RelationalDescriptor(tld.transmuc.model.Foo --> [DatabaseTable(Foos)])
Runtime Exceptions:
---------------------------------------------------------
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:535)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:476)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:435)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:673)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:618)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:206)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:460)
... 4 more
对我来说,映射是正确的。我检查了好几次。注意,在FooId中使用@Embedded注释与否在EL中没有区别
请注意Foo.postAddress关系的@JoinColumn注释,它们都是用insertable=false、updateable=false定义的,以指示嵌入的ID属性是可写的
注意,我并不是在寻找一个有效的解决方案,我只需删除只读insertable=false、updateable=false的内容就可以了。然而,问题是为什么上述映射在日食中失败。Hibernate对代码没有问题。此外,使用JPA 2.0@IdClass派生标识的以下功能等效代码(在EL中运行时不会出现问题)如下所示:
@Entity
@Table(name = "PostAddresses")
@IdClass(value = PostAddressId.class)
public class PostAddress implements Serializable
{
@Id
@Column(name = "contact_id")
private Integer contactId;
@Id
@Column(name = "ordinal_nbr")
private Integer ordinalNbr = 1;
...
}
public class PostAddressId implements Serializable
{
private Integer contactId;
private Integer ordinalNbr = 1;
...
}
@Entity
@Table(name = "Foos")
@IdClass(value = FooId.class)
public class Foo implements Serializable
{
@Id
@OneToOne
@JoinColumns(value = {
@JoinColumn(name = "contact_id", referencedColumnName = "contact_id", insertable = false, updatable = false),
@JoinColumn(name = "ordinal_nbr", referencedColumnName = "ordinal_nbr", insertable = false, updatable = false)
})
private PostAddress postAddress;
...
}
public class FooId implements Serializable
{
private PostAddressId postAddress;
...
}
如您所见,Foo.postAddress还包含只读insertable=false、updateable=false属性。Foo.postAddress通过将它们命名为相同的名称来映射到FooId.postAddress。FooId然后“指向”可写的PostAddressId类,它与上面的@EmbeddedId逻辑没有什么不同。至少逻辑对我来说没有什么不同。唯一的区别是,因为我使用@EmbeddedId,可写@Column注释最终位于@Embedded类中,这是有效的。(JPA只允许在@Embedded classes@Embedded、@Basic、@Column、@Temporal、@Enum和@Binary AFAIK中使用简单注释。)
我有什么遗漏吗?JPA2.0规范在这里说了什么
或者这是EclipseLink中的一个bug?
最后一点注意:这个问题显然类似于但不相同。同时,链接问题的EL已经修复,我使用的是固定版本的EL,所以问题不一样。这一个仅涉及JPA 2.0@EmbeddedId中@JoinColumn上的只读属性,使用EclipseLink中的嵌套ID类+@MapsId。EclipseLink将MapsId解释为表示该关系控制Foos表中定义的contact_ID和ordinal_nbr列。因此,当您将关系字段标记为只读时,这意味着这些字段没有可写映射-mapsId告诉提供程序需要从关系中使用值,但关系是只读的
你为什么要使用mapsId而不是仅仅将你的关系标记为ID然后使用pk类呢 在EclipseLink论坛上继续讨论以下主题:
@Entity
@Table(name = "PostAddresses")
@IdClass(value = PostAddressId.class)
public class PostAddress implements Serializable
{
@Id
@Column(name = "contact_id")
private Integer contactId;
@Id
@Column(name = "ordinal_nbr")
private Integer ordinalNbr = 1;
...
}
public class PostAddressId implements Serializable
{
private Integer contactId;
private Integer ordinalNbr = 1;
...
}
@Entity
@Table(name = "Foos")
@IdClass(value = FooId.class)
public class Foo implements Serializable
{
@Id
@OneToOne
@JoinColumns(value = {
@JoinColumn(name = "contact_id", referencedColumnName = "contact_id", insertable = false, updatable = false),
@JoinColumn(name = "ordinal_nbr", referencedColumnName = "ordinal_nbr", insertable = false, updatable = false)
})
private PostAddress postAddress;
...
}
public class FooId implements Serializable
{
private PostAddressId postAddress;
...
}