从列表中删除项目时遇到问题。该列表在超类中定义,但Hibernate注释应用于子类中的属性访问器。超类中有两种方法可以操作列表。 “添加”方法工作正常,但“删除”不会持续更改。我检查了我的Cascade设置,我似乎有正确的事情。我做的事情是不可能的。如果没有,我做错了吗?
以下是我的课程:
@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;
}
}
我使用TemporalAsset类的实例如下(请注意,我只使用“refresh”方法来演示行为。即使我刷新或关闭会话并打开新会话,列表也不会正确保留) :
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
感谢。
答案 0 :(得分:19)
您必须将Cascade显式指定为CascadeType.DELETE_ORPHAN。
尝试将代码更改为
@OneToMany
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}, mappedBy = "temporal")
部分来自休眠docs:
如果子对象的生命周期是 受到父母生命的限制 对象,让父母充满 生命周期对象通过指定 CascadeType.ALL和 org.hibernate.annotations.CascadeType.DELETE_ORPHAN (请参考Hibernate 语义参考指南 孤儿删除)
答案 1 :(得分:1)
尝试删除对Session.refresh()的调用。来自文档:
重新阅读给定的状态 来自底层数据库的实例。 不建议使用它 实现长期运行的会话 跨越许多业务任务。这种方法 然而,在某些特殊情况下是有用的 情况。例如
- 数据库触发器在插入或更新时更改对象状态
- 在同一会话中执行直接SQL(例如,批量更新)后
插入Blob或Clob后
http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)
如果在refresh()之前调用flush(),那也可能解决问题,因为flush()保证将对数据库执行任何挂起的SQL。在实践中,我几乎从未见过任何人使用refresh(),它看起来与您需要的代码不同。
本章的文档值得一读:
http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html
答案 2 :(得分:0)
您已在超类中将'content'字段标记为瞬态。我至少会怀疑这会造成问题。通过子类中的映射,您现在基本上具有两个相同属性的矛盾映射。
答案 3 :(得分:0)
这是当前推荐的方法。
@OneToMany(mappedBy = "temporal", orphanRemoval = true, cascade = CascadeType.ALL)