首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么merge()试图在反向@OneToMany集合中持久化/验证实体?

为什么merge()试图在反向@OneToMany集合中持久化/验证实体?
EN

Stack Overflow用户
提问于 2015-03-26 16:01:26
回答 1查看 936关注 0票数 1

我看到Hibernate (3.6.10)中的行为与我的心理模型不匹配,我想知道这是否意味着存在bug,是否有意识地决定打破(否则有效的)心理模型,或者我的心智模型是错误的。

我有一个双向的OneToMany/ManyToOne在父母和孩子之间的关系,其中父母有很多孩子,而Child是这种关系的所有者:

代码语言:javascript
复制
@Entity
public class Child {
    @ManyToOne
    @JoinColumn(name="PARENTID", nullable=false)
    private Parent parent;
}

@Entity
public class Parent {
    @OneToMany(mappedBy="parent", fetch=FetchType.LAZY)
    private List<Child> children;
}

以及我的测试(在@Transactional测试和SpringJunit4ClassRunner中):

代码语言:javascript
复制
@Test
public void test() {
    Child child = new Child();
    child.setName("TEST");
    childDao.saveOrUpdate(child);
    childDao.getSession.flush();
    childDao.getSession.evict(child);

    Parent parent = new Parent();
    parent.setChild(child);
    child.addParent(parent);

    childDao.merge(child);
}

我的心智模型说,修改“孩子”的父实体引用并保存“子”,会使父级和“子”之间关系的更改保持不变;Hibernate忽略了对“子”集合的更改。

但是,如果我创建新的(瞬态)子对象并将它们添加到一个独立的父对象中,当我调用sessionFactory.merge(parent)时,merge()调用似乎会检查父对象的children集合并拒绝合并,因为这些子对象是瞬态的,即使我的代码将在merge()调用返回时立即遍历这些子对象。(对于一个新的父对象,它的自然密钥与数据库中已经有一个的对象匹配,我得到了相同的行为。)

有一个与这个问题相关的符号(来自2007年修正的第五版第413页的底部):“合并包括所有值类型的属性以及所有元素的添加和删除。”如果语句是“任何非逆集合”,这将匹配我的心智模型(即,坚持所有将由saveOrUpdate()持久化的更改),但是在“任何”一词中包含逆集合与我的心智模型相冲突。

有人能解释为什么merge()在逆向集合(一个使用mappedBy)中考虑对象的状态,即使saveOrUpdate()会忽略它们吗?是否有任何设置可以指示merge()忽略这些实体?

注意:这个问题与JPA2和hibernate -为什么合并存储子实体而持久化不存储?不一样(虽然标题听起来完全相同),因为该作者正在尝试级联(而persist()没有发生这种情况),而我不希望自动级联行为。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-26 22:01:09

合并操作将传入的实体状态复制到附加实体或新加载的实体快照中。

我添加了一个GitHub测试来复制Hibernate 4.3.8的说法,它运行得很好。子实体在相反的一面被忽略,而一个瞬态的实体则被忽略。

这两个临时实体:

代码语言:javascript
复制
doInTransaction(session -> {
    Post _post = new Post("Post");
    _post.getComments().add(new Comment());
    session.persist(_post);
    return _post;
});

和超然的:

代码语言:javascript
复制
final Post post = doInTransaction(session -> {
    Post _post = new Post("Post");
    session.persist(_post);
    return _post;
});

doInTransaction(session -> {
    post.getComments().add(new Comment());
    session.merge(post);
});

被正确保存,而相反的一面则被忽略。

因为这在3.6.10下失败,并且在4.3.8下正常工作,这很可能只是Hibernate 3.6.10中的一个bug,在3.6.10到4.3.8之间的某个版本中修复了它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29283301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档