1. ? 循環分頁或者循環進行部分讀取處理數據的時候,使用 session.clear() ;
?
2. ? ?對應1+N(N+1)問題使用如下解決方式:
1): 使用createCriteria進行查詢(join fetch)
2):HQL -> join fetch
3): 使用@fetch設置LAZY
4):在@Entity下使用注解@BatchSize(size=5)
@BatchSize ?指定每次 讀 取數據的數量
?
3. List 與 iterate 進行遍歷取出數據庫數據的list();
區別1)List 直接取出對象 ? ? ??iterate先會取出組件,需要使用才會使用
?
區別2)同一個session中每次執行list()取出數據時都會發送SQL語句,但是iterate只會發出一條,默認會去session緩存去找;
?
4. 緩存,session級別的緩存稱為一級緩存,每個session都有獨立的一級緩存,例如多個線程同時取同一個對象數據;
解決方案:建立一個共用的總緩存(總緩存)二級緩存,如果找不到然后再到各自的session一級混村中尋找;具體操作如下:首先看緩存策略,
type : 其中memory支持緩存內存中,disk支持緩存存放硬盤中;
Cluster Safe :是否支持使用在集群環境;
Query Cache Supported:是否支持查詢緩存(3級緩存)
假設使用EhCacheProvider二級緩存:
1)修改hibernate.cfg.xml配置文件:
1 2 | < property ?name = "cache.use_second_level_cache" >true</ property > < property ?name = "cache.provider_class" >org.hibernate.cache.EhCacheProvider</ property > |
2) 在/hibernate-distribution-3.3.2.GA/project/etc/ehcache.xml 配置文件拷貝到項目中;
在ehcache.xml中默認如下設置:
1 | ? < diskStore ?path = "java.io.tmpdir" /> |
1 2 3 4 5 6 7 | < defaultCache ??? maxElementsInMemory = "10000" ??? eternal = "false" ??? timeToIdleSeconds = "120" ??? timeToLiveSeconds = "1200" ??? overflowToDisk = "true" ??? /> |
maxElementsInMemory:在內存中最多緩存的對象數量
eternal: 緩存內存對象是否永久保存不刪除
timeToIdleSeconds: ?當timeToIdleSeconds 周期時間沒有被使用過,自動清除掉;(秒)
timeToLiveSeconds: 緩存對象的生存時間(秒)后自動清楚;
overflowToDisk:溢出的時候是否放置在硬盤上
diskStore ?path:默認臨時存放硬盤緩存的路徑
注意:<cache name="sampleCache1" ? ?/> 可以自定義cache名,不自定義不指定默認是用 <defauleCache ? ..... />
3)將類使用二級緩存,直接在@Entity下使用注解 ? ?@Cache ?其設置如下:
常用的READ_ONLY (只讀),?READ_WRITE(讀寫)
其中@Cache(region="") 使用自定義ehcache.xml的自定義緩存策略設置 ~
4)加入ehcache的jar包,路徑如下:/hibernate-distribution-3.3.2.GA/lib/optional/ehcache/ehcache.jar
加入?commons-logging.jar包
? ? ? ? ? ? ?1. ? ?放入二級緩存如下規則:
? ? ? ? ? ? ? ? ? ?a) ? 經常訪問 ?b) 不經常改動(改動不大) c) 數據不是很大?例如用戶權限;
2. ? ? load 默認使用二級緩存,iterate 默認使用二級緩存
3. list 默認往二級緩存加數據,list查詢的使用不使用緩存
4. 如果要 query 查詢語句使用二級緩存,需要打開查詢緩存(同樣的重復的查詢!)
1) hibernate.cfg.xml配置文件加入配置:
<property name="cache.use_query_cache">true</property>
2) 使用Query的setCachable(true) 方法指明使用二級緩存 ;
?
5. ? ?緩存算法:LRU 、 LFU 、 FIFO
LRU: 最近最少被使用的; (時間)
LFU: 使用率比較少的;(次數)
FIFO:按照數據從0開始拿走(堆棧)
設置方法:在ehcache.xml繼續設置一個參數: memoryStoreEvictionPolicy="LRU"
?
6. 事務隔離機制(為了避免事務并發出現的問題)
1. read-uncommitted : 能讀取沒有提交的數據; 【會出現臟讀等問題,一般不設置此種】
2. read-committed : ?只有提交后才讀;Hibernate建議使用!【能解決臟讀但會出現不可重復讀和幻讀問題(手動解決)】
3. repeatable read : ? ? ?加鎖;(MySQL默認使用?repeatable read?)
4. serializable : ? 序列化,解決任何問題,但是效率最低;
MySQL?支持這四種事務隔離機制;?事務隔離級別越高效率越慢~
使用 select @@tx_isolation; ?查詢事務隔離機制;
? ? ?設置隔離機制:?set session tx_isolation='xxx'; ?
?
Hibernate解決并發事務方案:使用Hibernate悲觀鎖和樂觀鎖進行設置;
1)事務機制的值為1,2,4,8 (ps. 二進制為0001 ,0010,0100,1000 這樣算法效率高)
1.a)使用悲觀鎖:(依賴于數據庫的鎖 解決 repeatable read問題)
在讀取load數據的時候,加入第三個參數::
session.load(xxx.class, 1,LockMode.xxx);
LockMode的值如下:
一般只設置LockMode.UPGRADE
原因:
NONE: 無鎖的機制,Transaction結束時切換到此模式;
READ :在查詢的時候 hibernate會自動獲取鎖;
write ,insert, update hibernate 會自動獲取鎖;
以上 3種鎖的模式是hibernate內部使用的;
UPGRADE—NOWAIT ->是oracle數據庫 支持的鎖;
?
? ? ?1.b)使用樂觀鎖:(程序內使用字段version進行加鎖,與數據庫沒有關系)
可以定義一個version屬性,然后在getVersion上使用注解 @Version
注意:當并發的時候會報錯,那么找個錯誤交給我們自己來處理; ?
? ? ? ?悲觀與樂觀:悲觀一開始就進行加鎖,不論是否有其他事務來同時并發;但是樂觀鎖則不進行直接加鎖,而是等待更新時候進行檢查對比下,如果與去之前version不一致那么更新下即可;樂觀鎖效率高;