Hibernate JPA:@OneToMany删除旧的,插入新的而不刷新 [英] Hibernate JPA: @OneToMany delete old, insert new without flush

查看:145
本文介绍了Hibernate JPA:@OneToMany删除旧的,插入新的而不刷新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上从未完全了解休眠状态下的这种行为. 我在名为"Parent"的实体中使用@OneToMany关系,其注释如下:

I actually never quite understood this behavior in hibernate. I am using a @OneToMany relationship in a Entity called 'Parent', which is annotated like this:

@OneToMany(cascade = {CascadeType.ALL, CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval = true)
@JoinColumn(name = "entity_id", insertable = true, updatable = true, nullable = false)
private List<Child> children;

现在我要在一笔交易中执行以下操作:

Now I want to do the following within one transaction:

  • 获取父实体
  • 重复列出孩子的名单
  • 删除其中一个孩子
  • 插入一个新孩子

所以,基本上,我只是完全替换了其中一个孩子.

So, basically I am just entirely replacing one of the children.

据我了解的这个问题,我应该可以做这样的事情: (请注意,这只是一些Java伪代码来说明问题)

As far as I understand this problem, I should be able to do something like this: (please note that this is just some java pseudocode to illustrate the problem)

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteAndAdd(Long parentId, Long childId) {
  Parent parent = entityManager.find(parentId);
  for (Iterator it = parent.children.iterator(); it.hasNext();) {
    Child child = it.next();
    if (child.id == childId) {
      it.remove();
    }
  }
  Child newChild = new Child();
  parent.children.add(newChild);
}

但是,如果新的Child具有与旧的相同的唯一键值,则此操作将失败.因此,基本上,旧的子实体似乎没有被正确删除,而新的实体仍然存在.

However, this fails in case the new Child has the same unique key values as the old one. So, basically it seems like the old child entity isn't removed properly, before the new one is persisted.

如果我像这样在删除旧孩子和保留新孩子之间添加了entityManager.flush():

If I add a entityManager.flush() between deleting the old child and persisting the new child like this:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteAndAdd(Long parentId, Long childId) {
  Parent parent = entityManager.find(parentId);
  for (Iterator it = parent.children.iterator(); it.hasNext();) {
    Child child = it.next();
    if (child.id == childId) {
      it.remove();
    }
  }
  entityManager.flush();
  Child newChild = new Child();
  parent.children.add(newChild);
}

一切正常.在插入新的子对象之前,应删除该子对象.

Everything works fine. The child is deleted before the new one is inserted, as it should.

由于我不想假设休眠混合了发送到数据库的语句的顺序,所以我对休眠有其他假设,事实并非如此.为何后一个示例有效,而第一个示例无效?

As I don't want to asume that hibernate mixes up the order of the statements that are sent to the DB, there must be something else I am assuming about hibernate which isn't the case. Any ideas why the latter example works, while the first one doesn't?

休眠版本为3.5. 数据库是Mysql InnoDB

Hibernate version is 3.5. DB is Mysql InnoDB

推荐答案

Hibernate不了解也不尊重所有数据库约束(例如MySQL唯一约束).他们不打算很快解决这个已知问题.

Hibernate doesn't know about, nor respect, all database constraints (e.g. MySQL unique constraints). It's a known issue they don't plan on addressing anytime soon.

Hibernate具有

Hibernate has a defined order for the way operations occur during a flush.

实体删除总是在插入后发生.我唯一知道的答案是删除约束或添加其他刷新.

Entity deletions will always happen after inserts. The only answers I know about are to remove the constraint or add the additional flush.

顺便说一句,定义顺序的原因是,这是确保不违反外键约束(他们确实关心的约束之一)的唯一方法,即使用户执行了某些以外的操作订单.

By the way, the reason for the defined order is that this is the only way to guarantee foreign key constraints (one of the constraints they DO care about) aren't violated, even if the user does something out of order.

这篇关于Hibernate JPA:@OneToMany删除旧的,插入新的而不刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆