这应该是一项非常简单的任务,但我无法让它发挥作用。
我希望能够将对主要实体(让我们称之为Cat)挂起的延迟加载集合(让我们称之为小猫)的更改还原到单个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;
}
...
}
它不会从数据库中重新检索小猫(如记录所示)。我做错了什么?
答案 0 :(得分:3)
从二级缓存中驱逐小猫只要它们仍在第一级缓存中就没有效果。这是从中加载对象的位置。在第一级缓存中只有引用,i。即当您修改实例并从第一级缓存重新加载实体时,您将再次获得修改后的实例。
第一级缓存位于会话对象内。你必须使用Session.evict()
从会话中驱逐小猫。 (Session.clear()
或创建新会话具有相同的效果,但会强制重新加载存储在会话的第一级缓存中的所有对象。如果这是更好的解决方案,则取决于您的应用程序。)
我认为,经过这次修改后,您无需随时致电SessionFactory.evictCollection()
。顺便说一下,SessionFactory.evictCollection()
被标记为已弃用。