背景嘗試使用了Ehcache使用Spring和擴展了Hibernate的JpaRepository
這是我工作的自定義GenericDao接口(簡體)GenericDao
接口,這是任何DomainDao
實現:
GenericDao。 java的
@NoRepositoryBean
public interface GenericDao<E extends Persistable<K>, K extends Serializable> extends JpaRepository<E, K> {
public List<E> findAll();
public E persist(E entity);
}
GenericDaoImpl.java
public class GenericDaoImpl<E extends Persistable<K>, K extends Serializable> extends SimpleJpaRepository<E, K> implements GenericDao<E, K> {
private final JpaEntityInformation<E, ?> entityInformation;
private final EntityManager em;
private final Class<E> type;
public GenericDaoImpl(JpaEntityInformation<E, ?> entityInformation, EntityManager em) {
super(entityInformation, em);
this.entityInformation = entityInformation;
this.em = em;
this.type = entityInformation.getJavaType();
}
@Override
public List<E> findAll() {
return super.findAll();
}
@Override
@Transactional
public E persist(E entity) {
if (entityInformation.isNew(entity) || !EntityUtils.isPrimaryKeyGenerated(type) && !em.contains(entity)) {
em.persist(entity);
}
return entity;
}
}
例如,管理域Foo
和Bar
,你只需要創建兩個接口爲:
FooDao.java
public interface FooDao extends GenericDao<Foo, Integer> {
}
BarDao.java
public interface BarDao extends GenericDao<Bar, Integer> {
}
Spring
的@Autowired
註釋將自動實例化具有良好實體和主鍵類型的GenericDaoImpl
。
問題
我現在想加上我的DAO高速緩存過程,使用的Ehcache和EhCache Spring Annotations模型。
GenericDao.java
@NoRepositoryBean
public interface GenericDao<E extends Persistable<K>, K extends Serializable> extends JpaRepository<E, K> {
@Cacheable(cacheName = "dao")
public List<E> findAll();
@TriggersRemove(cacheName = "dao")
public E persist(E entity);
}
的applicationContext.xml
<ehcache:annotation-driven cache-manager="ehCacheManager" />
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
ehcache.xml中
<cache name="dao"
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
timeToIdleSeconds="86400"
timeToLiveSeconds="86400"
memoryStoreEvictionPolicy="LFU" />
親使用GenericDao
會導致緩存應該獨立於彼此管理每個DomainDao
。例如,對於當前的配置,如果我呼叫fooDao.findAll()
,然後barDao.persist(new Bar())
,由fooDao.findAll()
生成的緩存將被重置,因爲將使用相同的緩存(即<cache name="dao" />
),而不應該。
路線
我試圖實現自己的CacheKeyGenerator
,將考慮調用DomainDao
類型:
的applicationContext。XML
<ehcache:annotation-driven cache-manager="ehCacheManager" default-cache-key-generator="daoCacheKeyGenerator" />
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="daoCacheKeyGenerator" class="myapp.dao.support.DaoCacheKeyGenerator" />
DaoCacheKeyGenerator.java
public class DaoCacheKeyGenerator implements CacheKeyGenerator<DaoCacheKey> {
@Override
public DaoCacheKey generateKey(MethodInvocation methodInvocation) {
Class<?> clazz = methodInvocation.getThis().getClass().getInterfaces()[0];
Method method = methodInvocation.getMethod();
String methodName = method.getName();
Class<?>[] parameterClasses = method.getParameterTypes();
return new DaoCacheKey(clazz, methodName, parameterClasses);
}
@Override
public DaoCacheKey generateKey(Object... data) {
return null;
}
}
DaoCacheKey.java
public class DaoCacheKey implements Serializable {
private static final long serialVersionUID = 338466521373614710L;
private Class<?> clazz;
private String methodName;
private Class<?>[] parameterClasses;
public DaoCacheKey(Class<?> clazz, String methodName, Class<?>[] parameterClasses) {
this.clazz = clazz;
this.methodName = methodName;
this.parameterClasses = parameterClasses;
}
@Override
public boolean equals(Object obj) { // <-- breakpoint
if (obj instanceof DaoCacheKey) {
DaoCacheKey other = (DaoCacheKey) obj;
if (clazz.equals(other.clazz)) {
// if @TriggersRemove, reset any cache generated by a find* method of the same DomainDao
boolean removeCache = !methodName.startsWith("find") && other.methodName.startsWith("find");
// if @Cacheable, check if the result has been previously cached
boolean getOrCreateCache = methodName.equals(other.methodName) && Arrays.deepEquals(parameterClasses, other.parameterClasses);
return removeCache || getOrCreateCache;
}
}
return false;
}
@Override
public int hashCode() { // <-- breakpoint
return super.hashCode();
}
}
上述DaoCacheKey
的問題,就是equals
方法得到從來沒有所謂(中程序永遠不會中斷t),但是這樣做,所以該算法無法得到應用。
問題
有沒有人已經成功這樣的緩存?如果是的話如何?我的嘗試是否相關?如果是,如何使equals
方法調用,而不是hashCode
之一?通過擴展現有的CacheKeyGenerator
?如果是,哪一個?
你碰到你的應用程序,你必須實現的方式在GenericDao級別無效在高速緩存中各個條目的情況嗎?我很想知道實施是什麼。 – Glide