This is a Spring + JPA + Hibernate + EhCache application. I am facing some issues with cache (or I am assuming that is due to cache configuration). I am trying to cache some objects (it works fine, I can see in the cache statistics). The problem is that I want to flush the cache with a button if, for example, I need to update database directly to change some information from an external application.
这是一个Spring + JPA + Hibernate + EhCache应用程序。我面临一些缓存问题(或者我假设这是由于缓存配置)。我试图缓存一些对象(它工作正常,我可以在缓存统计中看到)。问题是我想用按钮刷新缓存,例如,我需要直接更新数据库以从外部应用程序更改某些信息。
The ExaminationForm entity is something like:
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...
Of course there are lot of more entities, but are working correctly and therefore obviated in the question. The DAO is more or less like:
当然,有更多的实体,但正在正常工作,因此在问题中避免了。 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();
}
In my applicationContext.xml of spring, I define the cache configuration as follows:
在我的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 related data only contains connection information and C3P0 variables. Therefore I do not copy here to avoid to much code.
Hibernate相关数据仅包含连接信息和C3P0变量。因此我不在这里复制以避免太多代码。
With the ehcache.xml configuration as:
使用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>
There are more data, but I do not want to copy thousands of lines of code to ask this question. If required, I can put more info later.
有更多的数据,但我不想复制数千行代码来提出这个问题。如果需要,我可以稍后提供更多信息。
Check that for evicting all classes I clean the region and also I execute getEntityManager().getEntityManagerFactory().getCache().evictAll();
to be sure that is removed. When I press the button I call the evictAllCache() in both DAOs. Probably is not the best approach and is redundant, but I am trying different approach without success. Also getAll()
has not any @Cacheable
annotation.
检查是否驱逐所有类我清理区域,并执行getEntityManager()。getEntityManagerFactory()。getCache()。evictAll();确保删除。当我按下按钮时,我在两个DAO中调用evictAllCache()。可能不是最好的方法而且是多余的,但我正在尝试不同的方法而没有成功。 getAll()也没有任何@Cacheable注释。
The problem is when I access to the getAll method of the DAO. First time, with Hibernate and cache debug set to on I get:
问题是当我访问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]
...
That is the expected behaviour. Is populating all Examinations data when getting all examinatios. But if I clean the cache, and execute again this method, I only get:
这是预期的行为。在获得所有考试时填写所有考试数据。但是,如果我清理缓存,并再次执行此方法,我只得到:
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]
...
Only IDs are retrieved. As in the GUI I can see the name and duration of each examination, means that the information is already available and hibernate does not need to retrieve it again. Therefore I am assuming that is cached somewhere.
仅检索ID。在GUI中,我可以看到每个检查的名称和持续时间,意味着信息已经可用,并且休眠不需要再次检索它。因此我假设它被缓存在某个地方。
The questions are:
问题是:
-
How can I force to reload all these data from database again?
如何强制再次从数据库重新加载所有这些数据?
-
Why getAll() is using cache if there is no annotation in the DAO's method neither in the entity to say that it must be cacheable.
为什么getAll()使用缓存,如果DAO的方法中没有注释,实体中既不能说它必须是可缓存的。
-
What is wrong in my
evictAllCache()
method?我的evictAllCache()方法有什么问题?
Obviously I am wrong somewhere but I am not able to find where.
显然我错了,但我找不到。
1 个解决方案
#1
It is possible that your queries are getting the objects from first level cache. Try to clean it with getEntityManager().clear();
您的查询可能是从第一级缓存获取对象。尝试使用getEntityManager()清除它.clear();
#1
It is possible that your queries are getting the objects from first level cache. Try to clean it with getEntityManager().clear();
您的查询可能是从第一级缓存获取对象。尝试使用getEntityManager()清除它.clear();