我有以下问题。 我使用JBoss 5.1,JPA / Hibernate和2级缓存。 我的系统几乎没有实体映射同一个数据库表。 例: Table FURNITURES由实体'Furn'和'Furniture'映射。
不能更改这些类。
现在,当我更改ID为1的'Furn'数据时,ID为1的'Furniture'仍然具有旧数据。在'Furn'更新后,是否有可能驱逐'家具'?
答案 0 :(得分: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
方法中,只需加载并逐出另一个实体。
另一种选择是使用interceptors,它可以帮助实现相同的功能,但根据我的口味,DAO路径更清晰。
答案 1 :(得分:2)
不推荐将同一个表映射到两个实体,所以我认为hibernate不会自动处理这个。
您可以为Furn实体实现一个后刷新侦听器,然后使用类似下面的代码来驱逐相应的Furniture对象
// 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());