2016-04-21 81 views
0

我認爲這是相當常見的模式,當我們有一個集合的實體並希望通過前端進行更新時。休眠:通過DTO的值更新實體

class Parent { 
    long id; 
    List<Child> childs; 
} 

class Child { 
    long id; 
    String property; 
} 

class ParentDTO { 
    long id; 
    List<ChildDTO> childs; 
} 

class ChildDTO { 
    long id; 
    String property; 
} 

現在我有一個像

public void createOrUpdate(ParentDTO parentDTO) { 
    Parent parent; 
    if (parentDTO.id == 0L) { 
     parent = new Parent(); 
     parent.childs = ChildDTO.convertToEntities(parentDTO.childs); 
    } else { 
     parent = em.find(Parent.class, parentDTO.id); 
     syncParent(parent, parentDTO); 
    } 

    em.saveOrUpdate(parent); 
} 

public static void syncParent(Parent parent, ParentDTO parentDTO) { 
    // this will cause issues due to setting session attached 
    // parent.childs collection to a new one 
    // parent.childs = ChildDTO.convertToEntities(parentDTO.childs); 

    // the better way is 
    parent.childs.clear(); 
    parent.childs.addAll(ChildDTO.convertToEntities(parentDTO.childs);) 

    // however let's look at convert method 
} 

public static List<Child> convertToEntities(List<ChildDTO> childDTOs) { 
    //let's skip iteration 
    Child child = new Child(); 
    child.id = childDTO.id; 
    child.property = childDTO.property; 
    // return childs 
} 

這裏的問題的方法是,如果我設置的ID從ChildDTO兒童試圖更新現有的兒童 - hibernate會拋出一個「獨立實體通過堅持「的例外。

我知道那個固定的方法有兩種:

  1. 不要設置一個ID,這樣孩子的將獲得新的ID每次都堅持時間
  2. 導線現有孩子的收集,並找到相應的childDTOs(具有相同的ID),然後複製值

如果您有更深的層次結構,第二種方法很麻煩。有沒有辦法做正確的事情,即當id設置爲Child時,hibernate會發現它實際上應該使用該id從Em重新加載Child(),並用新字段進行更新。

解決此問題的正確方法是什麼?

回答

0

看起來像一個完美的使用情況EntityManager::merge

合併給定的實體的狀態到當前的持久化上下文 。