这是一个Spring + JPA + Hibernate + EhCache应用程序。我面临一些缓存问题(或者我假设这是由于缓存配置)。我试图缓存一些对象(它工作正常,我可以在缓存统计中看到)。问题是我想用按钮刷新缓存,例如,我需要直接更新数据库以从外部应用程序更改某些信息。
ExamForm实体类似于:
@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();
}
在spring的applicationContext.xml中,我按如下方式定义缓存配置:
<!-- 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和缓存调试设置为on,我得到:
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中,我可以看到每个检查的名称和持续时间,意味着信息已经可用,并且休眠不需要再次检索它。因此我假设它被缓存在某个地方。
问题是:
如何强制再次从数据库重新加载所有这些数据?
如果DAO中没有注释,为什么getAll()正在使用缓存 方法既不在实体中说它必须是可缓存的。
我的evictAllCache()
方法出了什么问题?
显然我错了,但我无法找到。
答案 0 :(得分:2)
您的查询可能是从第一级缓存获取对象。尝试使用getEntityManager().clear();