2009-02-14 37 views
10

从列表中删除项目时遇到问题。该列表在超类中定义,但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类的一个实例如下(注意,我只使用“刷新”的方法来证明行为列表不正确地坚持,即使如果我刷新或关闭会话并打开新会话):

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 

谢谢。

回答

14

你必须明确地指定级联为CascadeType.DELETE_ORPHAN。

尝试从休眠docs更改代码

@OneToMany  
@Cascade(cascade = {CascadeType.ALL, CascadeType.DELETE_ORPHAN}, mappedBy = "temporal") 

部分:

如果子对象的寿命是由父 对象的寿命限定 ,让家长全 生命周期对象通过指定 CascadeType.ALL和 org.hibernate.annotations.CascadeType。DELETE_ORPHAN (请参阅Hibernate 参考指南 孤儿的语义删除)

+0

就是这样!非常感谢 – codefinger 2009-02-15 15:41:50

+0

CascadeType.DELETE_ORPHAN已弃用。有其他选择吗? – 2012-03-01 14:27:02

0

尝试删除对Session.refresh()的调用。从文档:

从底层数据库重新读取给定的 实例的状态。 这是不宜使用这 执行长期运行的会话, 跨越许多业务任务。然而,这种方法 在某些特殊的 的情况下是有用的。例如

  • 其中一个数据库触发器插入时改变对象状态或更新
  • 插入BLOB或CLOB
之后执行直接SQL(例如质量更新)在同一会话
  • http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html#refresh(java.lang.Object)

    如果你刷新()之前调用flush(),这可能会解决问题也一样,因为冲洗( )确保任何挂起的SQL将针对数据库执行。在实践中,我几乎从来没有见过任何人使用refresh(),它看起来不像你需要的代码。

    这从文档章节是值得一读:

    http://www.hibernate.org/hib_docs/v3/reference/en/html/objectstate.html

    +0

    我只在这里包括了刷新来演示行为。实际上,刷新不会将更改保留在列表中。我甚至可以关闭会话,打开一个新会话,并且该列表仍然具有值。 – codefinger 2009-02-15 00:39:14

    0

    你已经标记“内容”字段作为超一流的瞬态。我至少会怀疑这是造成问题的原因。通过子类中的映射,现在基本上有两个相同属性的相互矛盾的映射。