2

我有以下问题。我使用带有二级缓存的 JBoss 5.1、JPA/Hibernate。我的系统几乎没有映射同一个数据库表的实体。示例:表 FURNITURES 由实体 'Furn' 和 'Furniture' 映射。

这些类不能更改。

现在,当我更改 id 为 1 的“家具”的数据时,id 为 1 的“家具”仍然有旧数据。在“Furn”更新后是否有可能驱逐“Furniture”?

4

2 回答 2

3

当您更新/删除对象时,会向缓存层发送通知以反映这些更改。

缓存键甚至可能被广播到另一个服务器,因此它必须携带足够的有效负载来为远程端提供足够的信息来刷新相关条目。但另一方面,它不能太大,以最大限度地提高吞吐量。

如果您打开调试,您将看到以下结构(它可能会根据您的持久对象类型、标识符 - 复合与否等而有所不同):

cacheKey = {org.hibernate.cache.CacheKey}
|- key = {your.own.serializable.class}
|- type = {org.hibernate.type.ComponentType}
| |- typeScope = {org.hibernate.type.TypeFactory$TypeScopeImpl}
| | |- factory = {org.hibernate.impl.SessionFactoryImpl}
| |- propertyNames = {...}
| |- propertyTypes = {...}
| |- propertyNullability = {...}
| |- propertySpan = 2
| |- cascade = {...}
| |- joinedFetch = {...}
| |- isKey = true
| |- tuplizerMapping = {...}
|- entityOrRoleName = {java.lang.String} "my.Entity"
|- entityMode = {org.hibernate.EntityMode}
|- hashCode = 588688

如您所见,Hibernate 缓存键存储有关类名、id 类型等的信息。如果您有两种不同的类型,它们将被映射到两个不同的缓存键,因此您的问题。

为了修复它,您可以为这两个实体创建 DAO 类,并确保所有持久化这些实体的调用仅通过它们,而不会通过其他任何地方。然后,在两个条目的update/delete方法中简单地加载和驱逐另一个实体。

另一种选择是使用拦截器,它可以帮助实现相同的功能,但在我看来,DAO 路径更干净。

于 2012-10-29T23:12:53.783 回答
2

不建议将同一个表映射到两个实体,所以我认为 hibernate 不会自动处理这个问题。

您可以为 Furn 实体实现一个刷新后监听器,然后使用类似下面的代码来驱逐相应的家具对象

// This creates a proxy if not already loaded 
// other gives the object
Furniture furniture = session.load(Furniture.class,furn.getId());
// remove from first level cache
session.evict(furniture);
// remove from second level cache
sessionFactory.evict(Furniture.class,furn.getId());
于 2012-10-29T15:48:11.410 回答