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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Hibernate如何存储二级缓存条目

發(fā)布時間:2023/12/3 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate如何存储二级缓存条目 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

介紹

使用數(shù)據(jù)庫訪問抽象層的好處是可以透明地實現(xiàn)緩存,而不會泄漏到業(yè)務(wù)邏輯代碼中 。 Hibernate Persistence Context充當事務(wù)后寫式高速緩存 ,將實體狀態(tài)轉(zhuǎn)換轉(zhuǎn)換為DML語句。

持久性上下文充當邏輯事務(wù)存儲,并且每個Entity實例最多可以具有一個托管引用。 無論我們嘗試加載相同的實體多少次, 休眠會話都將始終返回相同的對象引用。 通常將此行為描述為第一級緩存 。

Hibernate持久化上下文 本身并不是一個緩存解決方案,服務(wù)于不同的目的不是提升應(yīng)用程序讀取操作的性能。 因為休眠會話綁定到當前正在運行的邏輯事務(wù),所以一旦事務(wù)結(jié)束,該會話將被銷毀。

二級緩存

適當?shù)木彺娼鉀Q方案必須跨越多個Hibernate會話 ,這就是Hibernate還支持其他二級緩存的原因。 第二級緩存綁定到SessionFactory生命周期,因此僅在關(guān)閉SessionFactory時會銷毀它(通常是在應(yīng)用程序關(guān)閉時)。 第二級緩存主要基于實體,盡管它也支持可選的查詢緩存解決方案。

默認情況下,二級緩存是禁用的,要激活它,我們必須設(shè)置以下Hibernate屬性:

properties.put("hibernate.cache.use_second_level_cache", Boolean.TRUE.toString()); properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");

一旦將hibernate.cache.use_second_level_cache屬性設(shè)置為true , RegionFactory將定義第二級緩存實現(xiàn)提供程序,并且hibernate.cache.region.factory_class配置是必需的。

要啟用實體級緩存,我們需要如下注釋可緩存實體:

@Entity @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

JPA還定義了@Cacheable批注,但它不支持在實體級別設(shè)置并發(fā)策略 。

實體加載流程

每當要加載實體時, 都會觸發(fā)LoadEevent并由 DefaultLoadEventListener對其進行如下處理:

Object entity = loadFromSessionCache( event, keyToLoad, options ); if ( entity == REMOVED_ENTITY_MARKER ) {LOG.debug("Load request found matching entity in context, but it is scheduled for removal;returning null" );return null; } if ( entity == INCONSISTENT_RTN_CLASS_MARKER ) {LOG.debug("Load request found matching entity in context, but the matched entity was ofan inconsistent return type;returning null");return null; } if ( entity != null ) {if ( traceEnabled ) {LOG.tracev("Resolved object in "+ "session cache: {0}",MessageHelper.infoString( persister,event.getEntityId(),event.getSession().getFactory() ));}return entity; }entity = loadFromSecondLevelCache( event, persister, options ); if ( entity != null ) {if ( traceEnabled ) {LOG.tracev("Resolved object in "+ "second-level cache: {0}",MessageHelper.infoString( persister,event.getEntityId(),event.getSession().getFactory() ));} } else {if ( traceEnabled ) {LOG.tracev("Object not resolved in "+ "any cache: {0}",MessageHelper.infoString( persister,event.getEntityId(),event.getSession().getFactory() ));}entity = loadFromDatasource( event, persister, keyToLoad, options ); }

始終首先檢查該會話,因為它可能已經(jīng)包含一個受管實體實例。 在訪問數(shù)據(jù)庫之前,已對二級緩存進行了驗證,因此其主要目的是減少數(shù)據(jù)庫訪問的次數(shù)。

二級緩存內(nèi)部

每個實體都存儲為CacheEntry ,并且實體水合狀態(tài)用于創(chuàng)建緩存條目值。

補水

在Hibernate命名法中, 水化是將JDBC ResultSet轉(zhuǎn)換為原始值數(shù)組時:

final Object[] values = persister.hydrate(rs, id, object, rootPersister, cols, eagerPropertyFetch, session );

水合狀態(tài)作為EntityEntry對象保存在當前運行的持久性上下文中 ,該對象封裝了加載時實體快照。 然后通過以下方式使用水合狀態(tài):

  • 默認的臟檢查機制 ,該機制將當前實體數(shù)據(jù)與加載時快照進行比較
  • 第二級緩存,其緩存項是根據(jù)加載時實體快照構(gòu)建的

反向操作稱為脫水 ,它將實體狀態(tài)復制到INSERT或UPDATE語句中。

二級緩存元素

盡管Hibernate允許我們操縱實體圖,但是二級緩存使用反匯編的水合狀態(tài)代替:

final CacheEntry entry = persister.buildCacheEntry( entity, hydratedState, version, session );

水合狀態(tài)在存儲在CacheEntry中之前先進行分解:

this.disassembledState = TypeHelper.disassemble(state, persister.getPropertyTypes(),persister.isLazyPropertiesCacheable() ? null : persister.getPropertyLaziness(),session, owner );

從以下實體模型圖開始:

我們將插入以下實體:

Post post = new Post(); post.setName("Hibernate Master Class");post.addDetails(new PostDetails()); post.addComment(new Comment("Good post!")); post.addComment(new Comment("Nice post!"));session.persist(post);

現(xiàn)在,我們將檢查每個單獨的實體緩存元素。

郵政實體有一個一對多關(guān)聯(lián)的注釋實體和逆一個-to-one關(guān)聯(lián)到PostDetails:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "post") private List<Comment> comments = new ArrayList<>();@OneToOne(cascade = CascadeType.ALL, mappedBy = "post", optional = true) private PostDetails details;

提取Post實體時:

Post post = (Post) session.get(Post.class, 1L);

關(guān)聯(lián)的緩存元素如下所示:

key = {org.hibernate.cache.spi.CacheKey@3855}key = {java.lang.Long@3860} "1"type = {org.hibernate.type.LongType@3861} entityOrRoleName = {java.lang.String@3862} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$Post"tenantId = nullhashCode = 31 value = {org.hibernate.cache.spi.entry.StandardCacheEntryImpl@3856}disassembledState = {java.io.Serializable[3]@3864} 0 = {java.lang.Long@3860} "1"1 = {java.lang.String@3865} "Hibernate Master Class"subclass = {java.lang.String@3862} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$Post"lazyPropertiesAreUnfetched = falseversion = null

CacheKey包含實體標識符,而CacheEntry包含實體分解的水合狀態(tài)。

Post條目緩存值由name列和id組成 ,它們由一對多 Comment關(guān)聯(lián)設(shè)置。

一對多關(guān)聯(lián)或反向一對一關(guān)聯(lián)都沒有嵌入Post CacheEntry中 。

該PostDetails實體主鍵是引用相關(guān)帖子實體的主鍵 ,因此具有與郵政實體一到一對一的關(guān)聯(lián)。

@OneToOne @JoinColumn(name = "id") @MapsId private Post post;

提取PostDetails實體時:

PostDetails postDetails = (PostDetails) session.get(PostDetails.class, 1L);

第二級緩存生成以下緩存元素:

key = {org.hibernate.cache.spi.CacheKey@3927}key = {java.lang.Long@3897} "1"type = {org.hibernate.type.LongType@3898} entityOrRoleName = {java.lang.String@3932} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$PostDetails"tenantId = nullhashCode = 31 value = {org.hibernate.cache.spi.entry.StandardCacheEntryImpl@3928}disassembledState = {java.io.Serializable[2]@3933} 0 = {java.sql.Timestamp@3935} "2015-04-06 15:36:13.626"subclass = {java.lang.String@3932} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$PostDetails"lazyPropertiesAreUnfetched = falseversion = null

由于實體標識符嵌入在CacheKey中 ,因此反匯編狀態(tài)僅包含createdOn實體屬性。

Comment實體與Post 具有多對一關(guān)聯(lián):

@ManyToOne private Post post;

當我們獲取評論實體時:

Comment comments = (Comment) session.get(Comment.class, 1L);

Hibernate生成以下二級緩存元素:

key = {org.hibernate.cache.spi.CacheKey@3857}key = {java.lang.Long@3864} "2"type = {org.hibernate.type.LongType@3865} entityOrRoleName = {java.lang.String@3863} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$Comment"tenantId = nullhashCode = 62 value = {org.hibernate.cache.spi.entry.StandardCacheEntryImpl@3858}disassembledState = {java.io.Serializable[2]@3862} 0 = {java.lang.Long@3867} "1"1 = {java.lang.String@3868} "Good post!"subclass = {java.lang.String@3863} "com.vladmihalcea.hibernate.masterclass.laboratory.cache.SecondLevelCacheTest$Comment"lazyPropertiesAreUnfetched = falseversion = null

反匯編狀態(tài)包含Post.id 外鍵引用和檢查列,因此鏡像了關(guān)聯(lián)的數(shù)據(jù)庫表定義。

結(jié)論

第二級緩存是關(guān)系數(shù)據(jù)緩存,因此它以規(guī)范化形式存儲數(shù)據(jù),并且每個實體更新僅影響一個緩存條目。 無法讀取整個實體圖,因為在第二級緩存條目中未實現(xiàn)實體關(guān)聯(lián)。

聚合實體圖以使寫入操作復雜化為代價,為讀取操作提供了更好的性能。 如果緩存的數(shù)據(jù)未規(guī)范化并散布在各種聚合模型中,則實體更新將不得不修改多個緩存項,從而影響寫入操作性能。

由于它反映了基礎(chǔ)關(guān)系數(shù)據(jù),因此二級緩存提供了各種并發(fā)策略機制,因此我們可以平衡讀取性能和強大的一致性保證。

  • 代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2015/04/how-does-hibernate-store-second-level-cache-entries.html

總結(jié)

以上是生活随笔為你收集整理的Hibernate如何存储二级缓存条目的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。