java Hibernate:@OneToMany:从“多”端删除实体会导致EntityNotFoundException
我拥有以下实体:
@Entity
public static class Parent {
@Id
@GeneratedValue
private Long id;
String st;
@OneToMany(mappedBy = "parent")
Set<Child> children = new HashSet<>();
// get,set
}
@Entity
public static class Child {
@Id
@GeneratedValue
private Long id;
String st;
@ManyToOne()
private Parent parent;
//get,set
}
注意,@OneToMany侧没有级联
我想要的是:
- 我有一个父母和一个孩子处于分离状态李>
- 现在我想根据某些条件删除子项,所以我正在访问所有子项,找到必要的子项并直接通过em.remove(child)删除它我将其从家长的收藏中删除李>
- 之后,我想改变一些属性的家长,并保存它也。 我发现EntityNotFound是个例外李>
我执行了一些调试,发现子集合是PersistentSet,它记住了storedSnapshot中的状态。所以,当我将父对象合并到上下文-Hibernate时,请对存储的快照执行一些操作,并尝试从DB加载子对象。当然,不存在这样的实体,因此会引发异常
因此,我可以做几件事:
- 带有@NotFound的映射集合(action=NotFoundAction.IGNORE)
- 从子集合中删除期间-强制转换到PersistentSet并将其清除李>
但这似乎是一个黑客
所以,
1.我做错了什么?看起来,直接删除子实体是正确的
2.有没有更优雅的处理方法
可复制示例:
@Autowired
PrentCrud parentDao;
@Autowired
ChiildCrud childDao;
@PostConstruct
public void doSomething() {
LogManager.getLogger("org.hibernate.SQL").setLevel(Level.DEBUG);
Parent p = new Parent();
p.setSt("1");
Child e = new Child();
e.setParent(p);
e.setSt("c");
p.getChildren().add(e);
Parent save = parentDao.save(p);
e.setParent(save);
childDao.save(e);
Parent next = parentDao.findAll().iterator().next();
next.setSt("2");
next.getChildren().size();
childDao.deleteAll();
next.getChildren().clear();
if (next.getChildren() instanceof PersistentSet) { // this is hack, not working without
((Map)((PersistentSet) next.getChildren()).getStoredSnapshot()).clear();
}
parentDao.save(next); // exception is thrwn here without hack
System.out.println("Success");
}
# 1 楼答案
您是否尝试过将fetch type更改为eager?关系违约
OneToMany: LAZY ManyToOne: EAGER ManyToMany: LAZY OneToOne: EAGER
可能是因为fetch方法而缓存了它
# 2 楼答案
你可以用
next.setChildren(new HashSet<>());
代替next.getChildren().clear();
来摆脱getStoredSnapshot()).clear()
但是,使用级联和删除将更加优雅