2011-05-15 19 views
2

我有以下設計:的EclipseLink:多列,一個對一,JPA 2.0使用@MapsId失敗,只讀上@JoinColumn(比較衍生身份)@EmbeddedId

Valid XHTML http://kawoolutions.com/media/nontransmuc-onetoone.png

簡單的邏輯: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 stuff。但問題是爲什麼上述映射在EclipseLink中失敗。 Hibernate有沒有問題與代碼。此外,以下,功能上等同代碼 - 這工作沒有問題在EL - 使用JPA 2.0 @IdClass派生身份樣子:

@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命名爲相同,Foo.postAddress被映射到FooId.postAddress。 FooId然後「指向可寫 PostAddressId類,這與上面的@EmbeddedId邏輯沒有區別。至少邏輯和我沒有什麼不同。唯一的區別是,因爲我使用的是@EmbeddedId,所以可寫@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的只讀屬性,在EclipseLink中使用嵌套ID類+ @MapsId。

回答

4

的EclipseLink解釋mapsId意味着關係控制在FOOS表中定義的CONTACT_ID和ordinal_nbr列。因此,當您將關係字段標記爲只讀時,這意味着這些字段沒有可寫映射 - mapsId通知提供程序需要使用關係中的值,但關係是隻讀的。

是否有任何理由爲什麼你使用mapsId而不是將你的關係標記爲ID然後使用PK類?

+1

主題在EclipseLink論壇中繼續:http://www.eclipse.org/forums/index.php/m/671130/ – Kawu 2011-05-16 20:18:58