hiberate緩存 一般而言,ORM的數據緩存應包含如下幾個層次:
1. 事務級緩存(Transcation Layer Cache)
2. 應用級/進程級緩存(Application/Process Layer Cache)
3. 分布式緩存(Cluster Layer Cache)
Hibernate數據緩存(Cache)分為兩個層次,以Hibernate語義加以區分,
可分為:
1. 內部緩存(Session Level,也稱為一級緩存)
2. 二級緩存(SessionFactory Level,也稱為二級緩存)
Hibernate中,緩存將在以下情況中發揮作用:
1. 通過id[主鍵]加載數據時每個實體唯一的OID
2. 延遲加載
@ Cache緩存:
1. Session level (一級緩存):
主要作用于:主鍵獲得的數據, 延遲初始化(Lazy Initialization)起作用.
狀態依賴于:Session的建立而建立(銷毀而銷毀).// Session是個Map容器!
清除Session對象: Session.Save()也是交給Session level來管理,很多的時候會發生OutOfMemoryError異常,所以要及時發送給數據庫session.flush(),清除session.clear()或session.evict(user1);
在SQL Server、Oracle, Hibernat設定屬性hibernate.jdbc.batch_size多少數據發送
<hibernate-configuration> <session-factory>
<property name="hibernate.jdbc.batch_size">100
</property> // MySQL是不支持的,
</session-factory>
<hibernate-configuration>
2. SessionFactory level(二級緩存)
二級緩存是SessionFactory級別的全局緩存, 是進程范圍或者集群范圍的緩存, 存放的對象的松散數據,可能出現并發問題, 需要采用適當的并發訪問策略,該策略為被緩存的數據提供了事務隔離級別。緩存適配器用于把具體的緩存實現軟件與Hibernate集成。第二級緩存是可選的,可以在每個類或每個集合的粒度上配置第二級緩存。
可以使用不同的緩存類庫,比如ehcache、oscache等,需要設置hibernate.cache.provider_class,之后,需要在映射文件中指定各個映射實體(以及collection)的緩存同步策略。Hibernate提供了一下4種內置的緩存同步策略:
1. read-only
只讀。對于不會發生改變的數據,可使用只讀型緩存。
2. nonstrict-read-write
如果程序對并發訪問下的數據同步要求不是非常嚴格,且數據更新操作頻率較低,可以采用本選項,獲得較好的性能。
3. read-write
嚴格可讀寫緩存。基于時間戳判定機制,實現了“read committed”事務隔離等級。可用于對數據同步要求嚴格的情況,但不支持分布式緩存。這也是實際應用中使用最多的同步策略。
4. transactional
事務型緩存,必須運行在JTA事務環境中。
如果使用查詢緩存,加上hibernate.cache.use_query_cache=true,只有當經常使用同樣的參數進行查詢時,這才會有些用處。該設置將會創建兩個緩存區域 - 一個用于保存查詢結果集(org.hibernate.cache.StandardQueryCache); 另一個則用于保存最近查詢的一系列表的時間戳(org.hibernate.cache.UpdateTimestampsCache)。 請注意:在查詢緩存中,它并不緩存結果集中所包含的實體的確切狀態;它只緩存這些實體的標識符屬性的值、以及各值類型的結果。 所以查詢緩存通常會和二級緩存一起使用。 絕大多數的查詢并不能從查詢緩存中受益,所以Hibernate默認是不進行查詢緩存的。如若需要進行緩存,請調用 Query.setCacheable(true)方法。這個調用會讓查詢在執行過程中時先從緩存中查找結果, 并將自己的結果集放到緩存中去。
Hibernate的二級緩存策略的一般過程如下:
1) 條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。
2) 把獲得的所有數據對象根據ID放入到第二級緩存中。
3) 當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。
4) 刪除、更新、增加數據的時候,同時更新緩存。
Hibernate的二級緩存策略,是針對于ID查詢的緩存策略,對于條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query緩存。
Hibernate的Query緩存策略的過程如下:
1) Hibernate首先根據這些信息組成一個Query Key,Query Key包括條件查詢的請求一般信息:SQL, SQL需要的參數,記錄范圍(起始位置rowStart,最大記錄個數maxRows),等。
2) Hibernate根據這個Query Key到Query緩存中查找對應的結果列表。如果存在,那么返回這個結果列表;如果不存在,查詢數據庫,獲取結果列表,把整個結果列表根據Query Key放入到Query緩存中。
3) Query Key中的SQL涉及到一些表名,如果這些表的任何數據發生修改、刪除、增加等操作,這些相關的Query Key都要從緩存中清空。
什么樣的數據適合存放到第二級緩存中?
1 很少被修改的數據
2 不是很重要的數據,允許出現偶爾并發的數據
3 不會被并發訪問的數據
4 參考數據
不適合存放到第二級緩存的數據?
1 經常被修改的數據
2 財務數據,絕對不允許出現并發
3 與其他應用共享的數據
無論何時,當給save()、update()或 saveOrUpdate()方法傳遞一個對象時,或使用load()、 get()、list()、iterate() 或scroll()方法獲得一個對象時, 該對象都將被加入到Session的內部緩存中。
當隨后flush()方法被調用時,對象的狀態會和數據庫取得同步。 如果你不希望此同步操作發生,或者你正處理大量對象、需要對有效管理內存時,你可以調用evict() 方法,從一級緩存中去掉這些對象及其集合。如若要把所有的對象從session緩存中徹底清除,則需要調用Session.clear(),不過最好先Session.flush()
SessionFactory也提供了移除緩存的方法,這些方法是:
sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class); //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections
對于事物管理的確定:
hibernate.cfg.xml :
<hibernate-configuration>
<session-factory>
....
<!-- 設定事務管理的工廠類 -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory </property>
</hibernate-configuration>
try {
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
....
tx.commit(); // 必須commit才會更新資料庫
} catch(HibernateException e) {
tx.rollback();
}
Postil: 對于MySQL處理機制要建立事物表類型的
類型的對照表:
Java
|
Hibernate
|
SQL
|
byte、java.lang.Byte
|
byte
|
TINYINT
|
short、java.lang.Short
|
short
|
SMALLINT
|
int、java.lang.Integer
|
integer
|
INGEGER
|
long、java.lang.Long
|
long
|
BIGINT
|
float、java.lang.Float
|
float
|
FLOAT
|
double、java.lang.Double
|
double
|
DOUBLE
|
java.math.BigDecimal
|
big_decimal
|
NUMERIC
|
char、java.lang.Character
|
character
|
CHAR(1)
|
boolean、java.lang.Boolean
|
boolean
|
BIT
|
java.lang.String
|
string
|
VARCHAR
|
boolean、java.lang.Boolean
|
yes_no
|
CHAR(1)('Y'或'N')
|
boolean、java.lang.Boolean
|
true_false
|
CHAR(1)('Y'或'N')
|
java.util.Date、java.sql.Date
|
date
|
DATE
|
java.util.Date、java.sql.Time
|
time
|
TIME
|
java.util.Date、java.sql.Timestamp
|
timestamp
|
TIMESTAMP
|
java.util.Calendar
|
calendar
|
TIMESTAMP
|
java.util.Calendar
|
calendar_date
|
DATE
|
byte[]
|
binary
|
VARBINARY、BLOB
|
java.lang.String
|
text
|
CLOB
|
java.io.Serializable
|
serializable
|
VARBINARY、BLOB
|
java.sql.Clob
|
clob
|
CLOB
|
java.sql.Blob
|
blob
|
BLOB
|
java.lang.Class
|
class
|
VARCHAR
|
java.util.Locale
|
locale
|
VARCHAR
|
java.util.TimeZone
|
timezone
|
VARCHAR
|
java.util.Currency
|
currency
|
VARCHAR
|
posted on 2007-05-15 14:07
???MengChuChen 閱讀(647)
評論(0) 編輯 收藏 所屬分類:
hibernate