1

这应该是一项非常简单的任务,但我无法让它发挥作用。

我希望能够将更改还原到一个延迟加载的集合(我们称之为小猫),它挂在一个单一的 Hibernate 会话中维护的主要实体(我们称之为猫)上。

集合是这样定义的(用猫和小猫代替我的呆板实体):

@Entity
@Table(name="CAT")
public class Cat {

    private Map<Long, Kitten> kittens;

    @OneToMany(fetch=FetchType.LAZY, mappedBy="mother", cascade={CascadeType.ALL})
    @MapKey(name="id")
    public Map<Long, Kitten> getKittens() {
        return kittens;
    }

    ...
}

@Entity
@Table(name="KITTEN")
public class Kitten {

   private Cat mother;

    @ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CadcadeType.MERGE)
    @JoinColumn(name="MOTHER_CAT_ID", nullable=false)
    public Cat getMother {
        return mother;
    }

    ...
}

用户可以在 kittens 集合中添加和删除他们心中的内容,而无需持久保存,直到他们明确保存并执行会话刷新。

但是如果用户选择恢复原始的小猫列表,则应该再次从数据库中检索。

我试图通过从二级缓存中逐出小猫集合然后使用以下模式从数据库中重新获取 Cat 实体来实现集合的完全还原:

public class CatDao {

    public Cat reset(Cat cat) {

        SessionFactory sessionFactory = Util.getSessionFactory();
        sessionFactory.evictCollection(Cat.class.getName() + ".kittens", cat.getId());

        Cat original = (Cat)this.session.get(Cat.class, cat.getId());
        Hibernate.initialize(original.getKittens());

        return original;
    }

    ...
}

它不会从数据库中重新检索小猫(如日志所示)。我究竟做错了什么?

4

1 回答 1

3

只要小猫还在一级缓存中,从二级缓存中驱逐小猫就没有任何效果。那是加载对象的地方。而在一级缓存中只有引用,即当你修改一个实例并从一级缓存重新加载实体时,你又得到了修改后的实例。

第一级缓存在会话对象内。您必须使用 将小猫从会话中逐出Session.evict()。(Session.clear()或创建一个新会话具有相同的效果,但会强制重新加载存储在会话的第一级缓存中的所有对象。这取决于您的应用程序是否是更好的解决方案。)

我认为经过此修改后,您无需随时致电SessionFactory.evictCollection()。顺便说一句,SessionFactory.evictCollection()被标记为已弃用。

于 2012-05-15T09:51:19.807 回答