redis作为hibernate的二级缓存
hibernate的二級緩存有好多,像ehcache。不過項(xiàng)目的緩存使用的是redis,而redis官方?jīng)]有實(shí)現(xiàn)hibernate的二級緩存接口,只得自己實(shí)現(xiàn)。看看公司的高手如何做的吧。
先看配置:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!-- entityManagerFactory --> ????<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" ????????depends-on="cacheManagerFactory"> ????????... ????????<property name="jpaProperties"> ????????????<props> ????????????????... ????????????????<prop key="hibernate.cache.use_second_level_cache">true</prop> ????????????????<!-- <prop key="hibernate.cache.use_query_cache">true</prop> --> ????????????????<prop key="hibernate.cache.region.factory_class">xxx.xxx.framework.cache.hibernate.CacheRegionFactory</prop> ????????????????... ????????????</props> ????????</property> ????</bean>?? ????? ????<!-- cache --> ????<bean id="cacheManager" class="xxx.xxx.framework.cache.redis.RedisCacheManager"> ????????<property name="connectionFactory" ref="redisConnectionFactory"/> ????????<property name="namespace" value="payment"/> ????</bean> ????? ????<bean id="cacheManagerFactory" class="xxx.xxx.framework.cache.hibernate.CacheManagerFactory"> ????????<property name="cacheManager" ref="cacheManager"/> ????</bean> |
cacheManager是redis緩存的配置,二級緩存實(shí)現(xiàn)類CacheRegionFactory里面會用到它,但是hibernate緩存配置的只是配置實(shí)現(xiàn)類,沒法注入CacheRegionFactory對象,所以這邊多了個cacheManagerFactory,注意配置中的depends-on。它的代碼:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public final class CacheManagerFactory implements DisposableBean { ????private static CacheManager CACH_EMANAGER; ????public void setCacheManager(CacheManager cacheManager) { ????????CACH_EMANAGER = cacheManager; ????} ????public static CacheManager getCacheManager() { ????????return CACH_EMANAGER; ????} ????@Override ????public void destroy() throws Exception { ????????CACH_EMANAGER = null; ????} } |
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | public class CacheRegionFactory implements RegionFactory { ????private static final long serialVersionUID = -1557439471733872383L; ????private CacheManager cacheManager; ????private static final AtomicLong CURRENT = new AtomicLong(); ????protected Settings settings; ????@Override ????public void start(Settings settings, Properties properties) throws CacheException { ????????cacheManager = CacheManagerFactory.getCacheManager(); ????????this.settings = settings; ????????Assert.notNull(cacheManager, "cacheManager is required,CacheManagerFactory must be init first"); ????} ????@Override ????public void stop() { ????????cacheManager = null; ????} ????@Override ????public boolean isMinimalPutsEnabledByDefault() { ????????return true; ????} ????@Override ????public AccessType getDefaultAccessType() { ????????return AccessType.NONSTRICT_READ_WRITE; ????} ????@Override ????public long nextTimestamp() { ????????return CURRENT.incrementAndGet(); ????} ????@Override ????public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { ????????return new EntityRegionImpl(regionName, cacheManager.getCache(shortRegionName(regionName)), settings, properties, metadata); ????} ????@Override ????public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { ????????return new NaturalIdRegionImpl(regionName, cacheManager.getCache(shortRegionName(regionName)), settings, properties, metadata); ????} ????@Override ????public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException { ????????return new CollectionRegionImpl(regionName, cacheManager.getCache(shortRegionName(regionName)), settings, properties, metadata); ????} ????@Override ????public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { ????????return new QueryResultsRegionImpl(regionName, cacheManager.getCache(shortRegionName(regionName)), settings, properties); ????} ????@Override ????public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException { ????????return new TimestampsRegionImpl(regionName, cacheManager.getCache(shortRegionName(regionName)), settings, properties); ????} ????private static String shortRegionName(String regionName) { ????????... ????} } |
以buildEntityRegion為例,返回的對象EntityRegion是hibernate的接口,EntityRegionImpl怎是我們的實(shí)現(xiàn)。先看看它的實(shí)現(xiàn):
?| 1 2 3 4 5 6 7 8 9 10 11 | public class EntityRegionImpl extends AbstractTransactionalDataRegion implements EntityRegion { ????public EntityRegionImpl(String regionName, Cache cache, Settings settings, Properties properties, CacheDataDescription metadata) { ????????super(regionName,cache, settings, properties, metadata); ????} ????@Override ????public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException { ????????return new EntityRegionAccessStrategyImpl(this, settings); ????} } |
先看它的父類,父類實(shí)現(xiàn)了hibernate的TansactionalDateRegion:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class AbstractTransactionalDataRegion extends AbstractRegion implements TransactionalDataRegion { ????private final CacheDataDescription metadata; ????public AbstractTransactionalDataRegion(String regionName, Cache cache, Settings settings, Properties properties, CacheDataDescription metadata) { ????????super(regionName, cache, settings, properties); ????????this.metadata = metadata; ????} ????@Override ????public boolean isTransactionAware() { ????????return false; ????} ????@Override ????public CacheDataDescription getCacheDataDescription() { ????????return metadata; ????} } |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | public class AbstractRegion implements Region { ????private static final AtomicLong CURRENT = new AtomicLong(); ????private String regionName; ????protected final Cache cache; ????protected final Properties properties; ????protected final Settings settings; ????protected final KeyGenerator keyGenerator = DefaultKeyGenerator.INSTANCE; ????public AbstractRegion(String regionName, Cache cache, Settings settings, Properties properties) { ????????this.regionName = regionName; ????????this.cache = cache; ????????this.settings = settings; ????????this.properties = properties; ????} ????@Override ????public String getName() { ????????return regionName; ????} ????@Override ????public void destroy() throws CacheException { ????} ????@Override ????public boolean contains(Object key) { ????????return cache.exists(key); ????} ????@Override ????public long getSizeInMemory() { ????????return -1; ????} ????@Override ????public long getElementCountInMemory() { ????????return cache.getStatistics().getSize(); ????} ????@Override ????public long getElementCountOnDisk() { ????????return -1; ????} ????@Override ????public Map toMap() { ????????return Collections.EMPTY_MAP; ????} ????@Override ????public long nextTimestamp() { ????????return CURRENT.incrementAndGet(); ????} ????@Override ????public int getTimeout() { ????????return 300; ????} ????public Object get(Object key) throws CacheException { ????????try { ????????????return postGet(cache.get(toKey(key))); ????????} catch (Throwable e) { ????????????throw new CacheException(e); ????????} ????} ????public void put(Object key, Object value) throws CacheException { ????????try { ????????????cache.put(toKey(key), value); ????????} catch (Exception e) { ????????????throw new CacheException(e); ????????} ????} ????public void evict(Object key) throws CacheException { ????????try { ????????????cache.evict(toKey(key)); ????????} catch (Exception e) { ????????????throw new CacheException(e); ????????} ????} ????public void evictAll() throws CacheException { ????????try { ????????????cache.clear(); ????????} catch (Exception e) { ????????????throw new CacheException(e); ????????} ????} ????private Object toKey(Object key) { ????????if (key instanceof CacheKey) { ????????????key = ((CacheKey) key).getKey(); ????????} ????????return keyGenerator.generate(key); ????} ...... |
現(xiàn)在我們回過頭看看EntityRegionImpl里面的EntityRegionAccessStrategyImpl實(shí)現(xiàn):
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 | public class EntityRegionAccessStrategyImpl extends AbstractAccessStrategy<EntityRegionImpl> implements EntityRegionAccessStrategy { ??? public EntityRegionAccessStrategyImpl(EntityRegionImpl region, Settings settings) { ??? ? ? super(region, settings); ??? } ??? @Override ??? public EntityRegion getRegion() { ??? ? ? return region; ??? } } |
先看看hibernate的這個接口的定義:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | public interface EntityRegionAccessStrategy extends RegionAccessStrategy{ ????/** ?????* Get the wrapped entity cache region ?????* ?????* @return The underlying region ?????*/ ????public EntityRegion getRegion(); ????/** ?????* Called after an item has been inserted (before the transaction completes), ?????* instead of calling evict(). ?????* This method is used by "synchronous" concurrency strategies. ?????* ?????* @param key The item key ?????* @param value The item ?????* @param version The item's version value ?????* @return Were the contents of the cache actual changed by this operation? ?????* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region} ?????*/ ????public boolean insert(Object key, Object value, Object version) throws CacheException; ????/** ?????* Called after an item has been inserted (after the transaction completes), ?????* instead of calling release(). ?????* This method is used by "asynchronous" concurrency strategies. ?????* ?????* @param key The item key ?????* @param value The item ?????* @param version The item's version value ?????* @return Were the contents of the cache actual changed by this operation? ?????* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region} ?????*/ ????public boolean afterInsert(Object key, Object value, Object version) throws CacheException; ????/** ?????* Called after an item has been updated (before the transaction completes), ?????* instead of calling evict(). This method is used by "synchronous" concurrency ?????* strategies. ?????* ?????* @param key The item key ?????* @param value The item ?????* @param currentVersion The item's current version value ?????* @param previousVersion The item's previous version value ?????* @return Were the contents of the cache actual changed by this operation? ?????* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region} ?????*/ ????public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException; ????/** ?????* Called after an item has been updated (after the transaction completes), ?????* instead of calling release().? This method is used by "asynchronous" ?????* concurrency strategies. ?????* ?????* @param key The item key ?????* @param value The item ?????* @param currentVersion The item's current version value ?????* @param previousVersion The item's previous version value ?????* @param lock The lock previously obtained from {@link #lockItem} ?????* @return Were the contents of the cache actual changed by this operation? ?????* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region} ?????*/ ????public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException; } |
我們的實(shí)現(xiàn)類同時(shí)有個父類AbstractAccessStrategy<EntityRegionImpl>,很多EntityRegionAccessStrategy因?yàn)槎际枪玫乃栽贏bstractAccessStrategy中實(shí)現(xiàn)了。看代碼:
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | public abstract class AbstractAccessStrategy<T extends AbstractTransactionalDataRegion> { ????protected final T region; ????protected final Settings settings; ????public AbstractAccessStrategy(T region, Settings settings) { ????????this.region = region; ????????this.settings = settings; ????} ????public boolean insert(Object key, Object value) throws CacheException { ????????return insert(key, value, null); ????} ????public boolean insert(Object key, Object value, Object version) throws CacheException { ????????return false; ????} ????public boolean afterInsert(Object key, Object value) throws CacheException { ????????return afterInsert(key, value, null); ????} ????public boolean afterInsert(Object key, Object value, Object version) throws CacheException { ????????return false; ????} ????public boolean update(Object key, Object value) throws CacheException { ????????return update(key, value, null, null); ????} ????public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException { ????????remove(key); ????????return false; ????} ????public boolean afterUpdate(Object key, Object value, SoftLock lock) throws CacheException { ????????return afterUpdate(key, value, null, null, lock); ????} ????public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException { ????????unlockItem(key, lock); ????????return false; ????} ????public Object get(Object key, long txTimestamp) throws CacheException { ????????return region.get(key); ????} ????public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException { ????????return putFromLoad(key, value, txTimestamp, version, settings.isMinimalPutsEnabled()); ????} ????public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException { ????????if (minimalPutOverride && region.contains(key)) { ????????????return false; ????????} else { ????????????region.put(key, value); ????????????return true; ????????} ????} ????public SoftLock lockItem(Object key, Object version) throws CacheException { ????????return null; ????} ????public SoftLock lockRegion() throws CacheException { ????????return null; ????} ????public void unlockItem(Object key, SoftLock lock) throws CacheException { ????????region.evict(key); ????} ????public void unlockRegion(SoftLock lock) throws CacheException { ????????region.evictAll(); ????} ????public void remove(Object key) throws CacheException { ????????region.evict(key); ????} ????public void removeAll() throws CacheException { ????????region.evictAll(); ????} ????public void evict(Object key) throws CacheException { ????????region.evict(key); ????} ????public void evictAll() throws CacheException { ????????region.evictAll(); ????} } |
上面的方法有些怪異如insert方法,里面就直接返回false了,問了高手,他說參考ehcache的實(shí)現(xiàn)。看了下ehcache的源碼它上面寫了:A no-op since this is an asynchronous cache access strategy。這個和hibernate接口定義的insert注釋有點(diǎn)出入:
?| 1 2 3 | * Called after an item has been inserted (before the transaction completes), ?????* instead of calling evict(). ?????* This method is used by "synchronous" concurrency strategies. |
轉(zhuǎn)http://my.oschina.net/yybear/blog/102216
總結(jié)
以上是生活随笔為你收集整理的redis作为hibernate的二级缓存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: memcached安装运行
- 下一篇: map-reduce的八个流程