【问题标题】:Hibernate: updating entity by the values from the DTOHibernate:通过 DTO 中的值更新实体
【发布时间】:2016-04-21 16:51:37
【问题描述】:

我认为当我们有一个包含一些集合的实体并希望通过前端对其进行更新时,这是很常见的模式。

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
}

这里的问题是,如果我从 ChildDTO 为 Child 设置 id 并尝试更新现有的 Child - hibernate 将抛出“传递给持久化的分离实体”异常。

我知道有两种解决方法:

  1. 不要设置id,这样子每次持久化时都会得到新的id
  2. 遍历现有childs的集合,找到对应的childDTO(id相同),然后复制值

如果你有更深的层次结构,第二种方法会很麻烦。有没有办法做正确的事情,即当 id 设置为 Child 时,休眠会发现它实际上应该使用来自 em 的 id 重新加载 Child() 并使用新字段更新它。

解决问题的正确方法是什么?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    看起来是EntityManager::merge 的完美用例:

    将给定实体的状态合并到当前持久化中 上下文。

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 1970-01-01
      • 2016-12-06
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      • 1970-01-01
      相关资源
      最近更新 更多