【问题标题】:Hibernate merge does not work with attribute as collectionHibernate 合并不适用于作为集合的属性
【发布时间】:2012-07-18 15:09:06
【问题描述】:

我是 Hibernate 的新手,我尝试持久化一个包含集合的实体。

我的类 User 包含一个 Set 属性。

class User{

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "user_id", referencedColumnName = "id")
   @Valid
   @Nullable
   public Set<Permission> getPermissions()
   {
      return permissions;
   }
}

当我使用新的权限集更新用户并尝试保存时,权限会再次重置为原始值,所有其他值都会更新,只有未更新的权限。

@Transactional(readOnly = false)
   @Override
   public User update(User user)
      entityManager.merge(user);
      entityManager.flush(); 
      entityManager.refresh(user); 
      return user;

我已经阅读了有关传递持久性和分离对象的信息,但我仍然无法使用它。

任何想法我做错了什么?

【问题讨论】:

    标签: java hibernate collections merge


    【解决方案1】:

    试试

    @Transactional(readOnly = false)
    @Override
    public User update(User user)
        return entityManager.merge(user);
    }
    

    其他调用是不必要的,并且会使您的代码混乱。并且您忽略了merge() 的结果,它是作为参数传递的分离的、保持不变的用户的更新、附加版本。

    另外,请注意,由于您在关联上有级联 ALL,因此上述内容不仅会更新用户字段以及与用户关联的权限。它还将合并权限。因此作为参数传递的用户权限状态将被复制到这些权限的附加版本并保存在数据库中。

    【讨论】:

    • 这就是我在开始阐述之前从一开始就拥有的东西。这样做会导致“拥有的实体实例不再引用具有 cascade="all-delete-orphan" 的集合”,或者如果我更改为“orphanRemoval = false”,则权限集未更新。
    • 不要替换集合本身。在集合中添加和删除元素。目前还不清楚你想做什么。是否要修改和删除权限?
    • 我尝试了我认为你的意思,但即使我添加了所有权限 public User update(User user, Set permissions) { for (Permission p : 权限) { user.getPermissions().add(p); } 用户合并用户 = entityManager.merge(user);返回合并用户; }
    • 如果您只想要这些权限,您应该在添加新权限之前执行user.getPermissions().clear()。删除旧的并添加新的。
    【解决方案2】:

    也许您要替换整个系列?我发现最好获取现有集合,并在其上调用 .add() 和 .remove() 以更新其内容,而不是替换整个内容。

    另外,您可以尝试改用@ElementCollection

    @ElementCollection
    @CollectionTable(name="PERMISSION",
            joinColumns={@JoinColumn(name="USER_ID")}
    )
    private Set<Permission> permissions;
    

    唯一需要注意的是 Permission 类必须用@Embeddable 标记,我不相信您可以直接查询权限作为顶级对象(您必须通过用户)。此外,Permission 对象不会有指向其用户的指针。

    这是一个关于如何查询它的示例 hql:

     select p from User u join u.permissions p where p.name=?
    

    【讨论】:

    • 我尝试了我认为您的意思,但即使我添加了所有权限 @Transactional(readOnly = false) @Override public User update(User user, Set权限){for(权限p:权限){user.getPermissions().add(p);用户mergedUser = entityManager.merge(user);返回合并用户; }
    猜你喜欢
    • 2018-06-25
    • 1970-01-01
    • 2011-08-31
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多