2016-11-16 53 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

相关问题