【发布时间】:2011-08-25 18:03:51
【问题描述】:
我有以下设计:
(来源:kawoolutions.com)
简单的逻辑:Foos 使用多列 PK 到 PostAddresses 使用相同的列(相同的键)。
以下是 JPA 2.0 @EmbeddedId 映射(使用 FooId 中的嵌套 ID 类 PostAddressId 和 Foo 中的 @MapsId 注释映射到它):
@Entity
@Table(name = "PostAddresses")
public class PostAddress implements Serializable
{
@EmbeddedId
private PostAddressId embeddedId;
...
}
@Embeddable
public class PostAddressId implements Serializable
{
@Column(name = "contact_id")
private Integer contactId;
@Column(name = "ordinal_nbr")
private Integer ordinalNbr = 1;
...
}
@Entity
@Table(name = "Foos")
public class Foo implements Serializable
{
@EmbeddedId
private FooId embeddedId;
@MapsId(value = "postAddressId")
@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;
...
}
@Embeddable
public class FooId implements Serializable
{
@Embedded
private PostAddressId postAddressId;
...
}
堆栈跟踪:
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, updatable = false定义的,表示嵌入的ID属性是可写的。
注意,我不是在寻找有效的解决方案,我可以简单地删除只读的 insertable = false, updatable = false 东西。然而,问题是 为什么 上述映射在 EclipseLink 中失败。 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, updatable = false 属性。 Foo.postAddress 通过将它们命名相同来映射到 FooId.postAddress。 FooId 然后“指向” writable PostAddressId 类,这与上面的@EmbeddedId 逻辑没有什么不同。至少逻辑对我来说没有什么不同。唯一的区别是,因为我使用的是@EmbeddedId,所以 writable @Column 注释最终在 @Embeddable 类中,这是有效的。 (JPA 只允许在 @Embeddable 类 @Embedded、@Basic、@Column、@Temporal、@Enum 和 @Binary AFAIK 中进行简单注释。)
我有什么遗漏吗? JPA 2.0 规范在这里说的是什么?
或者这是 EclipseLink 中的错误?
最后说明:这个问题显然与JPA (Hibernate, EclipseLink) mapping: why doesn't this code work (chain of 2 relationships using JPA 2.0, @EmbeddedId composite PK-FK)? 相似但不一样。链接问题的 EL 同时已修复,我正在使用该固定版本的 EL,因此问题不一样。这仅是关于 JPA 2.0 中 @EmbeddedId 中 @JoinColumn 的只读属性,使用嵌套 ID 类 + EclipseLink 中的 @MapsId。
【问题讨论】:
标签: hibernate jpa mapping jpa-2.0 eclipselink