2013-08-23 154 views
2

我在數據庫中有兩個表,A和B.表B有一個由兩個字段組成的ID。其中之一是A的外鍵。A的Id由插入序列自動生成。JPA:持久實體與複合主鍵

A: 
    ID (PK) 
    (*other fields*) 

B: 
    SOME_FIELD (PK) 
    A_ID (PK, FK to A) 

我已映射在JPA(休眠)以下JPA specification兩個表,在這種方式:

@Entity 
@Table(name = "A") 
public class A implements Serializable { 
    @Id 
    @SequenceGenerator(name = "A_SEQ", sequenceName = "A_SEQ") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "A_SEQ") 
    @Column(name = "ID") 
    private Long id; 
    (...) 
} 

@Entity 
@Table(name = "B") 
public class B implements Serializable { 
    @EmbeddedId 
    @AttributeOverride(name = "someField", column = @Column(name = SOME_FIELD)) 
    private BPK pk; 

    @MapsId("aId") 
    @ManyToOne 
    @JoinColumn(name = "A_ID") 
    private A a; 
    (...) 
} 

@Embeddable 
public class BPK implements Serializable { 
    private Long aId; 
    private String someField; 

    @Override 
    public boolean equals(Object o) { 
     (...) 
    } 

    @Override 
    public boolean hashCode() { 
     (...) 
    } 

    (...) 
} 

的問題是,當我試圖保存B對象調用entityManager.persist(二),其中BA被設置爲一個對象,它已經存在於數據庫中,我得到一個異常:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: package.name.A 

我不知道爲什麼會這樣。我試圖保存類B的對象,而不是A.我的實體類是否錯誤?或者,也許我不應該在這裏堅持下去?

+0

您需要在實體類中實現'Serializable'。 – iNan

+0

我執行此操作。我沒有複製「實現」部分,因爲我實現了更多的接口,並且不想在我的代碼中包含不必要的部分。用「implements Serializable」更新了這個問題。 – martaj

回答

3

可能是實體A不再被實體經理持有。你有沒有試過用B.的「新鮮」實例來設置B.a?

b.setA(get(b.a)); 
entityManager.persist(b); 

get(b.a)方法可不管你平時使用從您的數據源如發現實體A entityManager.getReference(A.class, a.id);

+0

謝謝,它有幫助。但我不明白爲什麼沒有這種「更新」就無法運作。對於其他實體,如果存在外鍵,但未包含在複合主鍵中,則只需調用entityManager.persist即可使用。在這種情況下,外鍵是主鍵的一部分嗎? – martaj

+0

複合主鍵是一個奇怪的野獸 - 我過去曾與他們鬥爭過。說實話,正因爲如此,我傾向於堅持主鍵的簡單標識,然後將組合作爲外鍵。 – KidTempo

+0

我認爲這與你創建兩個實體(B和BPK)和A是這兩個實體的一部分有關。由於A(作爲主鍵的一部分)對持久性至關重要,因此JPA堅持認爲它是「新鮮的」。 – KidTempo