2011-06-01 79 views
8

我有一個簡單的OneToMany關聯2對象Parent & Child如下所示。調用EntityManager.merge()時沒有設置Id EntityManager.merge()

母實體

@Entity 
    public class Parent { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 
    private String name; 
    @Version 
    private Long version; 

     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) 
     List<Child> children = new ArrayList<Child>(); 

     .... 
    } 

兒童實體

@Entity 
    public class Child { 
     @Id 
     @GeneratedValue(strategy = GenerationType.AUTO) 
     private Long id; 
     private String name; 
     @Version 
     private Long version; 
     ... 
    } 

以下是我的測試,加載現有的父增加了孩子和家長呼籲EntityManager.merge()。

@Test 
public void testParent(){ 
    Parent parent = (Parent) dao.loadParent(Parent.class, parentId); 

    Child c = new Child(); 
    c.setName("c"); 

    parent.getChildren().add(c); 

    dao.mergeEntity(parent); 

    Assert.assertNotNull(c.getId()); 
} 

測試ID的主鍵的斷言失敗。我看到記錄與自動分配的主鍵一起正確插入到數據庫中。

我所有的DAO調用都被包裝在具有傳播的事務中(如需要)。

+0

你應該給更多的信息,這是一個彈簧或EJB應用程序?.. – 2011-06-01 07:55:28

+0

你能張貼dao.mergeEntity(父母)的代碼? – Sylar 2011-06-01 07:55:47

+0

事務由彈簧以下處理是我的DAO代碼@Transactional(傳播= Propagation.REQUIRED) \t公共對象mergeEntity(對象實體){ \t \t返回em.merge(實體); \t} – Rakesh 2011-06-01 07:57:30

回答

12

EntityManager.merge(..)獲取一個實例並返回一個被管理的實例。而在短暫的實例的情況下,它會返回一個新的實例(不修改原)

所以你mergeEntity(..)方法應該return em.merge(entity)

+0

哈!我的壞我完全失去了,謝謝它現在的作品。 – Rakesh 2011-06-01 08:01:43

+0

不客氣。這是一個常見的錯誤。 – Bozho 2011-06-01 08:04:53

0

由於您的ID是由數據庫設置的,JPA/Hibernate只能在SQL語句被髮送到數據庫之後進行設置。如果將Hibernate配置爲顯示sql語句或將日誌更改爲DEBUG,則可能會看到在致電mergeEntity時沒有發出SQL語句。

使您的測試工作的一種方法應該是在對子ID進行斷言之前添加em.flush()。

管理交易的方式可能會有問題,但需要查看DAO的代碼以及在單元測試中獲取DAO參考的方式。

+0

@Transactional(傳播= Propagation.REQUIRED) \t公共對象mergeEntity(對象實體){ \t \t返回em.merge(實體); \t} – Rakesh 2011-06-01 07:59:04