java 休眠:从列表中删除项目不会持久
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/549961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate: Removing item from a List does not persist
提问by codefinger
I am having trouble when removing an item from a list. The list is defined in a superclass, but the Hibernate annotations are applied to property accessors in a subclass. There are two methods in the superclass that manipulate the list. The "add" method works fine, but the "remove" does not persist changes. I have checked my Cascade settings, and I seem to have things correct. Am I doing something that is impossible. If not, am I doing something incorrectly?
从列表中删除项目时遇到问题。该列表在超类中定义,但 Hibernate 注释应用于子类中的属性访问器。超类中有两种操作列表的方法。“添加”方法工作正常,但“删除”不会持续更改。我已经检查了我的 Cascade 设置,我似乎有正确的事情。我是不是在做一些不可能的事情。如果没有,我是否做错了什么?
Here are my classes:
这是我的课程:
@Entity
abstract class Temporal<T> {
@Id
@GeneratedValue
private Long id;
@Version
private Integer version = null;
@Transient
protected List<T> content = new ArrayList<T>();
public void remove(T value) {
// business logic ...
content.remove(value);
}
public void add(T value) {
// business logic ...
content.add(value);
}
}
@Entity
@AccessType("property")
class TemporalAsset extends Temporal<Asset> {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "temporal")
public List<Asset> getContent() {
return super.content;
}
protected void setContent(List<Asset> list) {
super.content = list;
}
}
I use an instance of the TemporalAsset class as follows (note that I am only use the "refresh" method to demonstrate the behavior. The list does not persist correctly even if I flush or close the session and open a new session):
我使用 TemporalAsset 类的一个实例如下(请注意,我只使用“刷新”方法来演示行为。即使我刷新或关闭会话并打开新会话,列表也不会正确保留):
temporalAsset.add(value1);
temporalAsset.getContent().size() == 1; // true
session.update(temporalAsset);
session.refresh(temporalAsset);
temporalAsset.getContent().size() == 1; // true
temporalAsset.remove(value1);
temporalAsset.getContent().size() == 0; // true
session.update(temporalAsset);
session.refresh(temporalAsset);
temporalAsset.getContent().size() == 0; // false, its 1
Thanks.
谢谢。
回答by FoxyBOA
You have to explicitly specify cascade as CascadeType.DELETE_ORPHAN.
您必须明确指定级联为 CascadeType.DELETE_ORPHAN。
Try to change code to
尝试将代码更改为
@OneToMany
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}, mappedBy = "temporal")
Part from hibernate docs:
部分来自休眠文档:
If the child object's lifespan is bounded by the lifespan of the parent object, make the parent a full lifecycle object by specifying CascadeType.ALL and org.hibernate.annotations.CascadeType.DELETE_ORPHAN (please refer to the Hibernate reference guide for the semantics of orphan delete)
如果子对象的生命周期受限于父对象的生命周期,则通过指定 CascadeType.ALL 和 org.hibernate.annotations.CascadeType.DELETE_ORPHAN 使父对象成为完整的生命周期对象(孤儿的语义请参考 Hibernate 参考指南删除)
回答by cliff.meyers
Try removing the calls to Session.refresh(). From the docs:
尝试删除对 Session.refresh() 的调用。从文档:
Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances. For example
- where a database trigger alters the object state upon insert or update
- after executing direct SQL (eg. a mass update) in the same session
- after inserting a Blob or Clob
从底层数据库重新读取给定实例的状态。不建议使用它来实现跨越许多业务任务的长时间运行的会话。但是,这种方法在某些特殊情况下很有用。例如
- 数据库触发器在插入或更新时更改对象状态的地方
- 在同一会话中执行直接 SQL(例如批量更新)后
- 插入 Blob 或 Clob 后
http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)
http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)
If you call flush() before refresh(), that might fix the problem too, since flush() guarantees that any pending SQL will be executed against the DB. In practice I've almost never seen anyone use refresh() and it doesn't look like from your code that you need it.
如果您在 refresh() 之前调用 flush(),那也可能解决问题,因为 flush() 保证将针对 DB 执行任何挂起的 SQL。在实践中,我几乎从未见过有人使用 refresh() 并且从您的代码中看起来并不像您需要它。
This chapter from the documentation is worth a read:
文档中的这一章值得一读:
http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html
http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html
回答by Jens Schauder
You have marked the 'content' field as transient in the super class. I would at least suspect that this is causing problems. With the mapping in the subclass, you basically have now two contradicting mappings for the same attribute.
您已在超类中将“内容”字段标记为瞬态。我至少会怀疑这会导致问题。使用子类中的映射,对于同一属性,您现在基本上有两个相互矛盾的映射。

