我看到Hibernate (3.6.10)中的行为与我的心理模型不匹配,我想知道这是否意味着存在bug,是否有意识地决定打破(否则有效的)心理模型,或者我的心智模型是错误的。
我有一个双向的OneToMany/ManyToOne在父母和孩子之间的关系,其中父母有很多孩子,而Child是这种关系的所有者:
@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中):
@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()没有发生这种情况),而我不希望自动级联行为。
发布于 2015-03-26 22:01:09
合并操作将传入的实体状态复制到附加实体或新加载的实体快照中。
我添加了一个GitHub测试来复制Hibernate 4.3.8的说法,它运行得很好。子实体在相反的一面被忽略,而一个瞬态的实体则被忽略。
这两个临时实体:
doInTransaction(session -> {
Post _post = new Post("Post");
_post.getComments().add(new Comment());
session.persist(_post);
return _post;
});和超然的:
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之间的某个版本中修复了它。
https://stackoverflow.com/questions/29283301
复制相似问题