2016-11-16 43 views
0
Library lib; //has a OneToMany rs to Book 
lib = new Library(); 

Book book; //has a OneToMany rs to Letters 
book = new Book(lib); 
book.save() 

book = new Book(lib); 
book.merge() //.save() will throw an exception (detached entity passed to persist jpa) because of lib, so I merge it 

Letters letters; 
letters = new Letters(book); 
letters.save(); //throws TransientPropertyValueException: object references an unsaved transient instance. 

出於測試目的,我想創建使用相同的庫多本圖書,並將它們保存。另外我想創建多個字母,使用同一本書並存儲它們。但我不知道如何實現這一點,因爲合併後的(書),這本書不再瞬態..(),對象仍標記爲未保存的瞬態的實例

感謝

編輯:增加了額外的類使事情變得更加清晰。

public abstract class Model implements Serializable { 
/** 
* Save the current object in the database. 
* 
*/ 
public void save() { 
    EntityManager entityManager = HibernateUtil.getEntityManagerFactory().createEntityManager(); 
    entityManager.getTransaction().begin(); 
    entityManager.persist(this); 
    entityManager.getTransaction().commit(); 
    entityManager.close(); 
} 
/** 
* Delete the current object from the database. 
* 
*/ 
public void delete() { 
    EntityManager entityManager = HibernateUtil.getEntityManagerFactory().createEntityManager(); 
    entityManager.getTransaction().begin(); 
    entityManager.remove(entityManager.contains(this) ? this : entityManager.merge(this)); 
    entityManager.getTransaction().commit(); 
    entityManager.close(); 
} 

public void merge(){ 
    EntityManager entityManager = HibernateUtil.getEntityManagerFactory().createEntityManager(); 
    entityManager.getTransaction().begin(); 
    entityManager.merge(this); 
    entityManager.getTransaction().commit(); 
    entityManager.close(); 
} 
} 

Book實體(Letter和圖書館實體看起來是一樣的)

@Entity 
@Table(name = "book") 
public class Book{ 

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@Column(name = "BOOK_ID") 
private Integer id; 

@OneToMany(fetch = FetchType.LAZY, mappedBy = "book", cascade = {CascadeType.ALL}) 
private List<Letters> letters; 

@ManyToOne(fetch = FetchType.LAZY,cascade = {CascadeType.ALL}) 
@JoinColumn(name = "lib_id") 
Library library; 

}

+1

我不能真正按照你的解釋,但merge()不附加參數。它返回另一個連接的實例。 –

+0

@JB Nizet hm。我的解釋在哪裏有問題?現在理解保存和合並之間的區別,但我仍然不知道如何在我的代碼中修復此問題。 – Lamevire

+1

不,我要說的是merge(foo)不會改變任何foo。它不會讓foo成爲一個託管對象。它**返回**另一個被管理的對象。 managedFoo = merge(foo)。 –

回答

0

什麼@JBNizet正打算說的是,你需要develop better your question, make it clearer

關於你的問題,我想你有類似的實體結構:

實體圖書館:

@Entity 
@Table(name = "library") 
public class Library { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "LIB_ID") 
    private Integer id; 

    @OneToMany(mappedBy = "library") 
    private List<Book> books; 

    // getters & setters 
} 

實體書:

@Entity 
@Table(name = "book") 
public class Book { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "BOOK_ID") 
    private Integer id; 

    @ManyToOne 
    @JoinColumn(name = "LIB_ID") 
    private Library library; 

    @OneToMany(mappedBy = "book") 
    private List<Letters> letters; 

    // ... 
} 

實體快報:

@Entity 
@Table(name = "letters") 
public class Letters { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "LETTERS_ID") 
    private Integer id; 

    @ManyToOne 
    @JoinColumn(name = "BOOK_ID") 
    private Book book; 

    // ... 

} 

這個問題通常與缺乏的cascade=CascadeType.ALL@ManyToOne映射,已經here說明。

但是,一旦你打開一個會話,保存/合併每個對象,然後提交/關閉它,你必須改變你的關係的級聯類型。這樣做:

  • 保持library對象的級聯類型的書類中爲@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
  • 更改所有其他級聯到CascadeType.MERGE。這樣,每次JPA必須保存整個對象樹時,它總會嘗試合併它們。
+0

對不起,我認爲這是明顯的如何與我的描述entitites。但你是對的。這就是類的樣子,有一點不同:我已經包含cascade = CascadeType.ALL else em.save(book); 會艾爾給我的獨立entitiy例外。你錯了,我不能在保存相同客戶對象的書上使用save()兩次,因爲在第一次保存後客戶不再是暫時的。 – Lamevire

+0

*我的意思是「lib不再是短暫的」 – Lamevire

+0

現在我明白你想要什麼了。我更新了我的答案,看看 – bosco

相關問題