有没有办法让 eclipselink/JPA 使用 redis 来保存和检索持久性单元级 (L2) 缓存?

Is there a way to make eclipselink/JPA use redis for saving and retrieving peristence-unit level (L2) cache?

我正在设置一个集群环境,我希望我的 JPA 的二级缓存在整个集群的节点中被复制。我使用 eclipselink 作为 JPA 提供程序,使用 redis 进行缓存管理。

没有官方或社区项目支持它。

但是,您可以实现自己的 CacheInterceptor

例如

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() {
    }
}

你可以看看这个使用Apache Ignite的项目,换成Redis试试。 sample project

缓存拦截器实现:Sample cache interceptor impl

点燃缓存拦截器:Sample Ignite cache interceptor project

Hazelcast 的其他示例项目:Sample Hazelcast cache interceptor project

简而言之,如果您需要使用 Redis 作为二级缓存,您需要实现自己的定制,或者 Hibernate 是您的最佳选择。它有一个可以插入的 redisson-hibernate 缓存提供程序 (redisson-hibernate)。

此致,