日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis作为hibernate的二级缓存

發布時間:2024/9/30 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis作为hibernate的二级缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

hibernate的二級緩存有好多,像ehcache。不過項目的緩存使用的是redis,而redis官方沒有實現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 <!-- 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緩存的配置,二級緩存實現類CacheRegionFactory里面會用到它,但是hibernate緩存配置的只是配置實現類,沒法注入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; ????} }
它就是負責生成cacheManager。注意getCacheManager是靜態方法。然后我們看redis二級緩存的實現類:


?
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) { ????????... ????} }
RegionFactory是hibernate的接口。在start里面通過調用CacheManagerFactory來獲取redis的CacheManager。這里主要還是buildXX的幾個方法,在這些方法里面通過? CacheManager和region獲取cache,然后再生成hibernate需要的緩存對象


以buildEntityRegion為例,返回的對象EntityRegion是hibernate的接口,EntityRegionImpl怎是我們的實現。先看看它的實現:

?
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); ????} }
這邊可以分兩部分看了一個是它的父類AbstractTransactionalDataRegion,另外一個是由EntityRegion繼承而來的buildAccessStrategy(Hibernate?EntityRegion的接口實現)。

先看它的父類,父類實現了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; ????} }
isTransactionAware是表示是否支持jta事務。然后再看它的父類AbstractRegion: ?
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); ????} ......
這里實現了hibernate region的一些接口,另外一些對于緩存的一些操作方法如:put\get\evict等也做了實現。

現在我們回過頭看看EntityRegionImpl里面的EntityRegionAccessStrategyImpl實現:

?
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的接口:EntityRegionAccessStrategy,字面意思就是緩存的訪問策略。

先看看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; }
它的父接口里面還有一些其他的接口如get,remove等可以直接看看源碼注釋上面都寫了。

我們的實現類同時有個父類AbstractAccessStrategy<EntityRegionImpl>,很多EntityRegionAccessStrategy因為都是公用的所以在AbstractAccessStrategy中實現了。看代碼:

?
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的實現。看了下ehcache的源碼它上面寫了:A no-op since this is an asynchronous cache access strategy。這個和hibernate接口定義的insert注釋有點出入:

?
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.
總之這塊不是很理解。

轉http://my.oschina.net/yybear/blog/102216

總結

以上是生活随笔為你收集整理的redis作为hibernate的二级缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。