cache evictAll() 后,一些缓存的元素没有被删除
Some cached elements are not deleted after cache evictAll()
这是一个 Spring + JPA + Hibernate + EhCache 应用程序。我遇到了一些缓存问题(或者我假设这是由于缓存配置引起的)。我正在尝试缓存一些对象(它工作正常,我可以在缓存统计信息中看到)。问题是我想用一个按钮刷新缓存,例如,如果我需要直接更新数据库以更改来自外部应用程序的某些信息。
ExaminationForm 实体类似于:
@Entity
public class ExaminationForm implements Serializable {
private static final long serialVersionUID = -7235473414679474757L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
private Long id;
@Column(nullable = false, length = 150)
private String name;
// Duration in minutes
private Integer duration;
//Getters and setters and other stuff...
当然还有更多的实体,但都在正常工作,因此在问题中被排除了。 DAO 或多或少像:
@Repository
public class ExaminationFormDao {
@Override
@Cacheable(value = "examinations", key = "#id")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public ExaminationForm get(Long id) {
return super.get(id);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public List<EntityClass> getAll() {
CriteriaQuery<EntityClass> query = getEntityManager().getCriteriaBuilder().createQuery(getEntityClass());
query.select(query.from(getEntityClass()));
try {
return getEntityManager().createQuery(query).getResultList();
} catch (NoResultException nre) {
return new ArrayList<EntityClass>();
}
}
@Caching(evict = { @CacheEvict(value = "examinations", allEntries = true) })
public void evictAllCache() {
getEntityManager().getEntityManagerFactory().getCache().evictAll();
}
在我的applicationContext.xml of spring中,我定义缓存配置如下:
<!-- Cache Configuration -->
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" />
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:ehcache.xml" p:shared="true" />
Hibernate 相关数据仅包含连接信息和 C3P0 变量。因此我不在这里复制以避免太多代码。
ehcache.xml配置为:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="usmocache">
<diskStore path="java.io.tmpdir" />
<defaultCache eternal="true" maxElementsInMemory="0"
overflowToDisk="false" statistics="true" />
<cache name="examinations" copyOnRead="true" copyOnWrite="true"
maxElementsInMemory="2000" eternal="false"
timeToIdleSeconds="0" timeToLiveSeconds="1200" overflowToDisk="false"
diskPersistent="false" memoryStoreEvictionPolicy="LFU" statistics="true" />
</ehcache>
资料比较多,但我不想复制几千行代码来问这个问题。如果需要,我可以稍后提供更多信息。
检查以清除所有 类 我清理该区域并执行 getEntityManager().getEntityManagerFactory().getCache().evictAll();
以确保它被删除。当我按下按钮时,我在两个 DAO 中调用了 evictAllCache()。可能不是最好的方法并且是多余的,但我正在尝试不同的方法但没有成功。 getAll()
也没有任何 @Cacheable
注释。
问题是当我访问 DAO 的 getAll 方法时。第一次,将 Hibernate 和缓存调试设置为开时,我得到:
SQL [qtp684428083-26] - select examinatio0_.ID as ID1_12_, examinatio0_.duration as duration2_12_, examinatio0_.name as name3_12_ from examination_form examinatio0_
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [1]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([duration2_12_] : [INTEGER]) - [15]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([name3_12_] : [VARCHAR]) - [Examination1Name]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [2]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([duration2_12_] : [INTEGER]) - [15]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([name3_12_] : [VARCHAR]) - [Examination2Name]
...
这是预期的行为。获取所有考试时正在填充所有考试数据。但是如果我清理缓存,然后再次执行这个方法,我只会得到:
SQL [qtp684428083-26] - select examinatio0_.ID as ID1_12_, examinatio0_.duration as duration2_12_, examinatio0_.name as name3_12_ from examination_form examinatio0_
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [1]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [2]
...
仅检索 ID。在 GUI 中我可以看到每次检查的名称和持续时间,这意味着信息已经可用并且 hibernate 不需要再次检索它。因此我假设它缓存在某处。
问题是:
如何强制从数据库重新加载所有这些数据?
如果 DAO 中没有注释,为什么 getAll() 使用缓存
实体中的方法都没有说它必须是可缓存的。
我的 evictAllCache()
方法有什么问题?
显然我哪里错了,但我找不到哪里。
您的查询可能正在从一级缓存中获取对象。尝试用 getEntityManager().clear();
清理它
这是一个 Spring + JPA + Hibernate + EhCache 应用程序。我遇到了一些缓存问题(或者我假设这是由于缓存配置引起的)。我正在尝试缓存一些对象(它工作正常,我可以在缓存统计信息中看到)。问题是我想用一个按钮刷新缓存,例如,如果我需要直接更新数据库以更改来自外部应用程序的某些信息。
ExaminationForm 实体类似于:
@Entity
public class ExaminationForm implements Serializable {
private static final long serialVersionUID = -7235473414679474757L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID", unique = true, nullable = false)
private Long id;
@Column(nullable = false, length = 150)
private String name;
// Duration in minutes
private Integer duration;
//Getters and setters and other stuff...
当然还有更多的实体,但都在正常工作,因此在问题中被排除了。 DAO 或多或少像:
@Repository
public class ExaminationFormDao {
@Override
@Cacheable(value = "examinations", key = "#id")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public ExaminationForm get(Long id) {
return super.get(id);
}
@Override
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public List<EntityClass> getAll() {
CriteriaQuery<EntityClass> query = getEntityManager().getCriteriaBuilder().createQuery(getEntityClass());
query.select(query.from(getEntityClass()));
try {
return getEntityManager().createQuery(query).getResultList();
} catch (NoResultException nre) {
return new ArrayList<EntityClass>();
}
}
@Caching(evict = { @CacheEvict(value = "examinations", allEntries = true) })
public void evictAllCache() {
getEntityManager().getEntityManagerFactory().getCache().evictAll();
}
在我的applicationContext.xml of spring中,我定义缓存配置如下:
<!-- Cache Configuration -->
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache" />
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="classpath:ehcache.xml" p:shared="true" />
Hibernate 相关数据仅包含连接信息和 C3P0 变量。因此我不在这里复制以避免太多代码。
ehcache.xml配置为:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="usmocache">
<diskStore path="java.io.tmpdir" />
<defaultCache eternal="true" maxElementsInMemory="0"
overflowToDisk="false" statistics="true" />
<cache name="examinations" copyOnRead="true" copyOnWrite="true"
maxElementsInMemory="2000" eternal="false"
timeToIdleSeconds="0" timeToLiveSeconds="1200" overflowToDisk="false"
diskPersistent="false" memoryStoreEvictionPolicy="LFU" statistics="true" />
</ehcache>
资料比较多,但我不想复制几千行代码来问这个问题。如果需要,我可以稍后提供更多信息。
检查以清除所有 类 我清理该区域并执行 getEntityManager().getEntityManagerFactory().getCache().evictAll();
以确保它被删除。当我按下按钮时,我在两个 DAO 中调用了 evictAllCache()。可能不是最好的方法并且是多余的,但我正在尝试不同的方法但没有成功。 getAll()
也没有任何 @Cacheable
注释。
问题是当我访问 DAO 的 getAll 方法时。第一次,将 Hibernate 和缓存调试设置为开时,我得到:
SQL [qtp684428083-26] - select examinatio0_.ID as ID1_12_, examinatio0_.duration as duration2_12_, examinatio0_.name as name3_12_ from examination_form examinatio0_
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [1]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([duration2_12_] : [INTEGER]) - [15]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([name3_12_] : [VARCHAR]) - [Examination1Name]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [2]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([duration2_12_] : [INTEGER]) - [15]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([name3_12_] : [VARCHAR]) - [Examination2Name]
...
这是预期的行为。获取所有考试时正在填充所有考试数据。但是如果我清理缓存,然后再次执行这个方法,我只会得到:
SQL [qtp684428083-26] - select examinatio0_.ID as ID1_12_, examinatio0_.duration as duration2_12_, examinatio0_.name as name3_12_ from examination_form examinatio0_
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [1]
TRACE BasicExtractor [qtp684428083-26] - extracted value ([ID1_12_] : [BIGINT]) - [2]
...
仅检索 ID。在 GUI 中我可以看到每次检查的名称和持续时间,这意味着信息已经可用并且 hibernate 不需要再次检索它。因此我假设它缓存在某处。
问题是:
如何强制从数据库重新加载所有这些数据?
如果 DAO 中没有注释,为什么 getAll() 使用缓存 实体中的方法都没有说它必须是可缓存的。
我的
evictAllCache()
方法有什么问题?
显然我哪里错了,但我找不到哪里。
您的查询可能正在从一级缓存中获取对象。尝试用 getEntityManager().clear();