2012-02-28 105 views
12

我使用JPA2與EclipseLink的實施@ManyToOne映射無法保存父ID

![簡單的表結構] [1]

這裏有兩個表,我試圖映射和JPA註釋。

public class Story implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    Integer id; 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column (name="DATE_CREATED") 
    Date dateCreated; 
    String title; 
    String description; 
    @Column(name="AUTHOR_ID") 
    Integer authorId; 
    @Column(name="COUNTRY_ID") 
    Integer countryId; 
    private String reviews; 

    @OneToMany(mappedBy = "story", cascade=CascadeType.ALL) 
    private List<Tip> tipList; 
} 

public class Tip implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private Integer id; 
    private String description; 
    private Integer vote; 

    @ManyToOne (cascade=CascadeType.ALL) 
    @JoinColumn(name="STORY_ID", referencedColumnName="ID") 
    private Story story; 
} 

作爲一個簡單的例子,我想在同一個事務中堅持一個故事和一些故事相關的技巧。 這裏的代碼確實是,部分:

Story newStory = new Story(title, body, ...); 

EntityTransaction transaction = em.getTransaction().begin(); 
    boolean completed = storyService.create(newStory); 
    //The tips are saved as a List<String>. This methods creates the needed List<Tip> from the Strings 
    List<Tip> tips = TipUtil.getTipList(tipList); 
    newStory.setTipList(tips) 
transaction.commit(); 

我沒有錯誤,所有的實體在數據庫中堅持着。問題是在小費表story_id字段總是NULL。我可以想象,JPA無法從故事表中獲得新的id。這裏的正確方法是什麼?

LE

在代碼的當前狀態,該Tip實體仍然存在,但該國ID仍無效。

回答

6

對於JPA,始終建議以雙向關係更新雙方的關係。這是爲了確保數據在您的應用程序層中是一致的,與數據庫無關。

但是,您必須更新雙向關係中關係的擁有方。

因此,設定/不設定

story.setTipList(tips) 

是你。但是如果你想改變正常的DB反映,然後你們必須調用

tip.setStory(story) 

Tip是擁有方在這裏,按你的代碼。 此外你的代碼看起來不完整。原因是,

  • storyService.create(newStory)返回的實體被管理,但不是newStory。所以只是設置newStory.setTipList(tips)將不會更新分區
5

因爲您需要更新每個孩子的父鏈接故事。

它的做法是在Story類中創建一個addTip(提示提示)方法。

這種方法做:

tip.setStory(this); 
tipList.add(tip); 

如果您不需要bedirectional的方法,你可以刪除這個故事領域的提示,這將解決您的問題

+1

我想知道是否沒有更自動的方式來做到這一點。更重要的是,我真的不認爲刪除提示中的故事字段是一個聰明的想法,因爲這樣,他將需要擺脫'@PrimaryKeyJoinColumn(name =「STORY_ID」,referencedColumnName =「ID」 )',讓JPA不知道應該如何進行加入。這正是我通過閱讀這個主題所瞭解的。如果我錯了,請讓我知道。 – Dragos 2012-02-28 11:50:26

+0

Ebean有自動解決方案,但JPA實現不提供自動解決方案。 – Palesz 2012-03-08 15:10:14

0

你不應該使用PrimaryKeyJoinColumn,只是JoinColumn,但擁有完整的課程有助於給出特定的答案。

PrimaryKeyJoinColumn只有在story_id也是Tip的id(提示中沒有id)並且存在重複的基本映射時纔會使用。它應該很少被使用,並且在JPA 2.0中不再需要,因爲不再需要重複的id映射。

+0

嗨!感謝您的答覆!我更新了我的問題。我添加了所有實體屬性以及在更改'@ PrimaryKeyJoinColumn'註釋後發生的更改。我希望現在更清楚。 – Ionut 2012-02-28 14:38:10

1

卸下

@Column(名稱= 「STORY_ID」) 私人整數storyId;

您已經聲明它@JoinColumn(name =「STORY_ID」,referencedColumnName =「ID」)

那就是爲什麼你所得到的錯誤多可寫的映射存在的領域tip.STORY_ID]

+0

謝謝!事實上,沒有其他錯誤,但'提示'實體不再被持久 – Ionut 2012-02-28 17:35:47

+0

根據實現,在雙向關係中,你必須設置關係的兩種方式(我不確定是否在eclipselink中是這樣的,但它可以值得一試)。因此,嘗試將newStory設置爲列表提示的每個提示。另外,行「boolean completed = storyService.create(newStory);」在transaction.commit之前放置它會是更多的邏輯; – Pau 2012-02-29 10:16:31