Hibernate 冬眠。在更新子列表时删除

Hibernate 冬眠。在更新子列表时删除,hibernate,jpa,orm,Hibernate,Jpa,Orm,我在Hibernate中有标准的@ManyToOne关联。更新时,我正在创建新的实体(使用new关键字)并用必要的值(也插入了ID)填充它。值来自UI。以同样的方式,我创建了新的子对象集合,用值填充每个子对象(也插入了ID),并将集合存储在父对象中(使用setter或addAll()方法) 所以我的问题是:如何在更新父集合时删除父集合中的所有对象,并用新集合替换它们。在新集合中,有些对象是全新的,有些只需要更新(它们插入了ID) 我学习了orhanremovation,但它没有帮助,因为父对象必

我在Hibernate中有标准的
@ManyToOne
关联。更新时,我正在创建新的实体(使用
new
关键字)并用必要的值(也插入了ID)填充它。值来自UI。以同样的方式,我创建了新的子对象集合,用值填充每个子对象(也插入了ID),并将集合存储在父对象中(使用setter或
addAll()
方法)

所以我的问题是:如何在更新父集合时删除父集合中的所有对象,并用新集合替换它们。在新集合中,有些对象是全新的,有些只需要更新(它们插入了ID)

我学习了
orhanremovation
,但它没有帮助,因为父对象必须处于“托管”状态(因此子集合上的
clear()
将不起作用),而不是像我的示例中那样处于瞬态。

update或saveOrUpdate()方法不考虑数据库中对象的当前状态,而是更新对象的所有当前属性。因此,在您的情况下,当您使用其集合更新新对象时,它不会处理旧集合,而是会更新对象的新集合。因此,数据库中既有旧集合,也有新集合

要用新集合覆盖旧集合,应该使用merge()方法,它首先将具有相同id的对象加载到持久化上下文中,然后将分离对象的状态复制到持久化对象,然后考虑对象是否脏。如果是这样,它将使用更改保持新对象

以下代码可以演示上述说明:

    // Initial the persistent layer
    DAOLayer daoLayer = new DAOLayer();

    // Persist the parent object with 1 child
    Parent parent = new Parent("parent");
    parent.addChild(new Child("child"));
    Parent persistentParent = daoLayer.merge(parent);

    // Create the new parent object with the same Id stored in DB
    Parent newParent = new Parent("parent");
    newParent.setId(persistentParent.getId());
    newParent.addChild(new Child("child"));

    // Update the new parent object
    persistentParent = daoLayer.merge(newParent);

上述代码在数据库中生成一个子项。如果将merge()方法更改为saveOrUpdate()方法,则会在数据库中产生两个子项。

创建父项,创建子项,然后用子项填充父项。你说父母是暂时的。在这种情况下,如何保存集合?我无法从您的描述中理解这一点。@mvb13是的,家长处于瞬态状态。我只需将子列表添加到父级并保存父级(级联操作很好)。但我想从父级(和DB)中删除旧集合,并用新集合(我添加到新创建的临时父级)替换它。如果保存父级,这意味着它不是临时集合,则必须将其持久化或分离。如果它处于分离状态,请重新附加它,而不是使用孤立删除,这是您应该使用它的情况。我不确定是否理解您的问题,但如果您正在更新,则应从数据库中获取现有实体,修改它们,然后提交。您不应该每次使用
new
并设置ID来创建新对象。@AdamDyga ok,谢谢。这意味着每次我需要更新对象时,我都应该检索实体,从UI中用新值填充它,并调用
会话#saveOrupdate
?感谢您的明确回答。但无论如何,从你的观点来看,在我的情况下,哪种方式更可取:1。显式创建新实体,向其插入ID,用新值更新它,然后使用
merge()
2。使用
get()
检索实体(在事务中)并使用新值更新检索到的实体(hibernate将自动刷新更改),这取决于您管理实体的方式。如果您检索对象,将其发送到UI,然后UI更改该对象,则更适合使用merge()方法,因为您不需要检查哪些属性已更改。但是,如果您在Web中提出一些字段(例如搜索条件),您确切地知道要更改哪些字段,您可以加载持久实体并对其进行更改。在我看来,我更喜欢使用merge()方法。它也是JPA中的标准方法(JPA不支持update()和saveOrUpdate()方法)。这似乎适用于关系的例外情况。我想这是因为不支持删除孤儿?