Ich benutze Hibernate 4.3.11.Final mit Spring 3.2.11.RELEASE. Ich bin verwirrt, warum meine Cache-Räumung nicht funktioniert. Ich habe diesen Satz in meinem DAO ...Warum wird meine Entität nicht aus meinem Second-Level-Cache entfernt?
@Override
@Caching(evict = { @CacheEvict("main") })
public Organization save(Organization organization)
{
return (Organization) super.save(organization);
}
@Override
@Cacheable(value = "main")
public Organization findById(String id)
{
return super.find(id);
}
und hier ist mein Frühling Config ...
<cache:annotation-driven key-generator="cacheKeyGenerator" />
<bean id="cacheKeyGenerator" class="org.mainco.subco.myproject.util.CacheKeyGenerator" />
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cacheManager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:configLocation="classpath:ehcache.xml"
p:shared="true" />
<util:map id="jpaPropertyMap">
<entry key="hibernate.show_sql" value="true" />
<entry key="hibernate.dialect" value="org.mainco.subco.myproject.jpa.subcoMysql5Dialect" />
<entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
<entry key="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
<entry key="hibernate.cache.use_second_level_cache" value="true" />
<entry key="hibernate.cache.use_query_cache" value="false" />
<entry key="hibernate.generate_statistics" value="true" />
<entry key="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE" />
</util:map>
<bean id="sharedEntityManager"
class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Doch im folgenden Test wird meine Einheit nicht aus dem Cache vertrieben zu werden, das weiß ich, weil die Zeile mit „Trefferanzahl # 3:“ druckt „3“, während die Zeile mit „Trefferanzahl # 2:“ druckt ‚2‘
private net.sf.ehcache.Cache m_cache
@Autowired
private net.sf.ehcache.CacheManager ehCacheManager;
@Before
public void setup()
{
m_cache = ehCacheManager.getCache("main");
m_transactionTemplate = new TransactionTemplate(m_transactionManager);
} // setup
...
@Test
public void testCacheEviction()
{
final String orgId = m_testProps.getProperty("test.org.id");
// Load the entity into the second-level cache
m_transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
m_orgSvc.findById(orgId);
return null;
});
final long hitCount = m_cache.getStatistics().getCacheHits();
System.out.println("hit count #1:" + hitCount);
m_transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
final Organization org = m_orgSvc.findById(orgId);
System.out.println("hit count:" + m_cache.getStatistics().getCacheHits());
org.setName("newName");
m_orgSvc.save(org);
return null;
});
// Reload the entity. This should not incur a hit on the cache.
m_transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
System.out.println("hit count #2:" + m_cache.getStatistics().getCacheHits());
final Organization newOrg = m_orgSvc.findById(orgId);
System.out.println("hit count #3:" + m_cache.getStatistics().getCacheHits());
return null;
});
Was die richtige Konfiguration ist mir zu erlauben, eine Einheit zu vertreiben. von meiner zweiten le vel Cache
Edit:? Die CacheKeyGenerator Klasse ich in meinem Anwendungskontext verwiesen wird, definiert unter
public class CacheKeyGenerator implements KeyGenerator
{
@Override
public Object generate(final Object target, final Method method,
final Object... params) {
final List<Object> key = new ArrayList<Object>();
key.add(method.getDeclaringClass().getName());
key.add(method.getName());
for (final Object o : params) {
key.add(o);
}
return key;
}
}
Als solche muss ich einen „Schlüssel“ nicht definieren für jede @Cacheable Anmerkung die ich bevorzugen (weniger Code). Ich weiß jedoch nicht, wie dies für CacheEviction gilt. Ich dachte, die Annotation @CacheEvict würde das gleiche Schlüsselgenerierungsschema verwenden.
Weil ich dies in meinem Anwendungskontext (von meiner Frage), '
Dave
Ihr Schlüsselgenerator generiert unterschiedliche Schlüssel für die beiden Methoden, was wiederum zu einer falschen Schlüsselübereinstimmung und somit zu keiner Räumung führt. Aktivieren Sie Debug-Protokolle, um dies zu überprüfen. Sie werden Spring-Caching-Protokolle sehen, die Ihnen den logischen Fehler bei der Generierung des Schlüssels anzeigen. – manish
Ich habe eine [Beispielanwendung] (https://github.com/manish-in-java/stackoverflow-questions/tree/master/35640220) erstellt, um Ihnen zu demonstrieren, dass meine Antwort funktioniert. Sie können es herunterladen und es als 'mvn clean test' ausführen, um alle Tests zu sehen. Es gibt einen Test, um den Cache-Status entsprechend Ihrer Anrufe zu überprüfen. Ich schlage vor, dass Sie mein Beispiel nehmen und Ihren Code hinzufügen, ohne Ihren benutzerdefinierten Schlüsselgenerator zuerst. Die Dinge sollten funktionieren, wenn Sie keine Änderungen am Arbeitsprobe vornehmen. Dann stecken Sie Ihren Schlüsselgenerator ein, um zu sehen, wo der Fehler ist. – manish