Java 有没有办法让eclipselink/JPA使用redis来保存和检索peristence单位级(L2)缓存?
我正在设置一个集群环境,我希望我的JPA的二级缓存能够在集群的节点中复制。我使用eclipselink作为JPA提供商,使用redis进行缓存管理。没有官方或社区项目支持它 但是,您可以实现自己的 例如Java 有没有办法让eclipselink/JPA使用redis来保存和检索peristence单位级(L2)缓存?,java,jpa,redis,eclipselink,redisson,Java,Jpa,Redis,Eclipselink,Redisson,我正在设置一个集群环境,我希望我的JPA的二级缓存能够在集群的节点中复制。我使用eclipselink作为JPA提供商,使用redis进行缓存管理。没有官方或社区项目支持它 但是,您可以实现自己的 例如 import org.eclipse.persistence.descriptors.ClassDescriptor; 导入org.eclipse.persistence.internal.identitymap.CacheKey; 导入org.eclipse.persistence.inter
import org.eclipse.persistence.descriptors.ClassDescriptor;
导入org.eclipse.persistence.internal.identitymap.CacheKey;
导入org.eclipse.persistence.internal.IdentityMap.IdentityMap;
导入org.eclipse.persistence.internal.sessions.AbstractSession;
导入org.eclipse.persistence.sessions.interceptors.CacheInterceptor;
导入org.eclipse.persistence.sessions.interceptors.CacheKeyInterceptor;
导入java.util.Map;
公共类MyRedisCacheInterceptor扩展了CacheInterceptor{
私有最终MyCacheProvider缓存支持;
私有最终字符串缓存名;
public DefaultCacheInterceptor(IdentityMap targetIdentityMap,AbstractSession interceptedSession,
字符串cacheName、DefaultCacheSupport(缓存支持){
super(targetIdentityMap,interceptedSession);
this.cacheSupport=cacheSupport;
this.cacheName=cacheName;
}
@凌驾
公共对象克隆(){
返回null;
}
@凌驾
受保护的CacheKeyInterceptor createCacheKeyInterceptor(CacheKey wrappedCacheKey){
final long longKey=(long)wrappedCacheKey.getKey();
CacheKeyInterceptor newKey=新CacheKeyInterceptor(wrappedCacheKey){
@凌驾
公共对象getObject(){
返回cacheSupport.getOrCreateCache(cacheName).get(longKey);
}
@凌驾
公共void集合对象(对象){
getOrCreateCache(cacheName).put(longKey,object);
}
};
返回newKey;
}
@凌驾
公共布尔containsKey(对象主键){
返回cacheSupport.getOrCreateCache(cacheName).containsKey(primaryKey);
}
@凌驾
公共映射getAllFromIdentityMapWithEntityPK(对象[]pkList,类描述符描述符,抽象会话){
返回null;
}
@凌驾
公共映射getAllCacheKeysFromIdentityMapWithEntityPK(对象[]pkList,类描述符描述符,抽象会话){
返回null;
}
@凌驾
公开无效释放(){
}
}
您可以看看这个使用ApacheIgnite的项目,用Redis替换它,然后再试一次。
缓存侦听器Impl:
Ignite缓存拦截器:
Hazelcast的其他样本项目:
简而言之,如果您需要使用Redis作为二级缓存,那么您需要实现自己的定制,或者Hibernate是您的最佳选择。它有一个redisson hibernate缓存提供程序,您可以将其插入()
在考虑远程二级缓存的正确性和性能方面时,可能会有所帮助。它涵盖了Hibernate如何与二级缓存交互,我不确定它在EclipseLink中是如何工作的(我假设有很多相似之处)。这是一个有趣的想法。我的猜测正确吗?您的意图是将其用于一种二级缓存,这种缓存将在集群的节点之间共享?@Captain yes。像HibernateRedis一样,我希望使用redis在集群中的所有节点上共享eclipselink二级缓存。谢谢。它工作了,但几乎不需要做什么更改,因为在第一次从DB中检索并将
CacheKeyInterceptor
的setObject
放入缓存时,将向您的bean传递一个空对象,即此时不会设置此对象的任何属性。因此,立即将其放入redis将把这个空对象放入缓存,这将是无用的。现在,作为一种解决方法,我将bean放在redis中的updateAccess
中,在正确设置对象的属性后将调用该bean。
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.sessions.interceptors.CacheInterceptor;
import org.eclipse.persistence.sessions.interceptors.CacheKeyInterceptor;
import java.util.Map;
public class MyRedisCacheInterceptor extends CacheInterceptor {
private final MyCacheProvider cacheSupport;
private final String cacheName;
public DefaultCacheInterceptor(IdentityMap targetIdentityMap, AbstractSession interceptedSession,
String cacheName, DefaultCacheSupport cacheSupport) {
super(targetIdentityMap, interceptedSession);
this.cacheSupport = cacheSupport;
this.cacheName = cacheName;
}
@Override
public Object clone() {
return null;
}
@Override
protected CacheKeyInterceptor createCacheKeyInterceptor(CacheKey wrappedCacheKey) {
final long longKey = (long) wrappedCacheKey.getKey();
CacheKeyInterceptor newKey = new CacheKeyInterceptor(wrappedCacheKey) {
@Override
public Object getObject() {
return cacheSupport.getOrCreateCache(cacheName).get(longKey);
}
@Override
public void setObject(Object object) {
cacheSupport.getOrCreateCache(cacheName).put(longKey, object);
}
};
return newKey;
}
@Override
public boolean containsKey(Object primaryKey) {
return cacheSupport.getOrCreateCache(cacheName).containsKey(primaryKey);
}
@Override
public Map<Object, Object> getAllFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session) {
return null;
}
@Override
public Map<Object, CacheKey> getAllCacheKeysFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session) {
return null;
}
@Override
public void release() {
}
}