hiberate緩存 一般而言,ORM的數(shù)據(jù)緩存應(yīng)包含如下幾個(gè)層次:
1. 事務(wù)級(jí)緩存(Transcation Layer Cache)
2. 應(yīng)用級(jí)/進(jìn)程級(jí)緩存(Application/Process Layer Cache)
3. 分布式緩存(Cluster Layer Cache)
Hibernate數(shù)據(jù)緩存(Cache)分為兩個(gè)層次,以Hibernate語(yǔ)義加以區(qū)分,
可分為:
1. 內(nèi)部緩存(Session Level,也稱為一級(jí)緩存)
2. 二級(jí)緩存(SessionFactory Level,也稱為二級(jí)緩存)
Hibernate中,緩存將在以下情況中發(fā)揮作用:
1. 通過(guò)id[主鍵]加載數(shù)據(jù)時(shí)每個(gè)實(shí)體唯一的OID
2. 延遲加載
@ Cache緩存:
1. Session level (一級(jí)緩存):
主要作用于:主鍵獲得的數(shù)據(jù), 延遲初始化(Lazy Initialization)起作用.
狀態(tài)依賴于:Session的建立而建立(銷毀而銷毀).// Session是個(gè)Map容器!
清除Session對(duì)象: Session.Save()也是交給Session level來(lái)管理,很多的時(shí)候會(huì)發(fā)生OutOfMemoryError異常,所以要及時(shí)發(fā)送給數(shù)據(jù)庫(kù)session.flush(),清除session.clear()或session.evict(user1);
在SQL Server、Oracle, Hibernat設(shè)定屬性hibernate.jdbc.batch_size多少數(shù)據(jù)發(fā)送
<hibernate-configuration> <session-factory>
<property name="hibernate.jdbc.batch_size">100
</property> // MySQL是不支持的,
</session-factory>
<hibernate-configuration>
2. SessionFactory level(二級(jí)緩存)
二級(jí)緩存是SessionFactory級(jí)別的全局緩存, 是進(jìn)程范圍或者集群范圍的緩存, 存放的對(duì)象的松散數(shù)據(jù),可能出現(xiàn)并發(fā)問(wèn)題, 需要采用適當(dāng)?shù)牟?/span>發(fā)訪問(wèn)策略,該策略為被緩存的數(shù)據(jù)提供了事務(wù)隔離級(jí)別。緩存適配器用于把具體的緩存實(shí)現(xiàn)軟件與Hibernate集成。第二級(jí)緩存是可選的,可以在每個(gè)類或每個(gè)集合的粒度上配置第二級(jí)緩存。
可以使用不同的緩存類庫(kù),比如ehcache、oscache等,需要設(shè)置hibernate.cache.provider_class,之后,需要在映射文件中指定各個(gè)映射實(shí)體(以及collection)的緩存同步策略。Hibernate提供了一下4種內(nèi)置的緩存同步策略:
1. read-only
只讀。對(duì)于不會(huì)發(fā)生改變的數(shù)據(jù),可使用只讀型緩存。
2. nonstrict-read-write
如果程序對(duì)并發(fā)訪問(wèn)下的數(shù)據(jù)同步要求不是非常嚴(yán)格,且數(shù)據(jù)更新操作頻率較低,可以采用本選項(xiàng),獲得較好的性能。
3. read-write
嚴(yán)格可讀寫緩存。基于時(shí)間戳判定機(jī)制,實(shí)現(xiàn)了“read committed”事務(wù)隔離等級(jí)。可用于對(duì)數(shù)據(jù)同步要求嚴(yán)格的情況,但不支持分布式緩存。這也是實(shí)際應(yīng)用中使用最多的同步策略。
4. transactional
事務(wù)型緩存,必須運(yùn)行在JTA事務(wù)環(huán)境中。
如果使用查詢緩存,加上hibernate.cache.use_query_cache=true,只有當(dāng)經(jīng)常使用同樣的參數(shù)進(jìn)行查詢時(shí),這才會(huì)有些用處。該設(shè)置將會(huì)創(chuàng)建兩個(gè)緩存區(qū)域 - 一個(gè)用于保存查詢結(jié)果集(org.hibernate.cache.StandardQueryCache); 另一個(gè)則用于保存最近查詢的一系列表的時(shí)間戳(org.hibernate.cache.UpdateTimestampsCache)。 請(qǐng)注意:在查詢緩存中,它并不緩存結(jié)果集中所包含的實(shí)體的確切狀態(tài);它只緩存這些實(shí)體的標(biāo)識(shí)符屬性的值、以及各值類型的結(jié)果。 所以查詢緩存通常會(huì)和二級(jí)緩存一起使用。 絕大多數(shù)的查詢并不能從查詢緩存中受益,所以Hibernate默認(rèn)是不進(jìn)行查詢緩存的。如若需要進(jìn)行緩存,請(qǐng)調(diào)用 Query.setCacheable(true)方法。這個(gè)調(diào)用會(huì)讓查詢?cè)趫?zhí)行過(guò)程中時(shí)先從緩存中查找結(jié)果, 并將自己的結(jié)果集放到緩存中去。
Hibernate的二級(jí)緩存策略的一般過(guò)程如下:
1) 條件查詢的時(shí)候,總是發(fā)出一條select * from table_name where …. (選擇所有字段)這樣的SQL語(yǔ)句查詢數(shù)據(jù)庫(kù),一次獲得所有的數(shù)據(jù)對(duì)象。
2) 把獲得的所有數(shù)據(jù)對(duì)象根據(jù)ID放入到第二級(jí)緩存中。
3) 當(dāng)Hibernate根據(jù)ID訪問(wèn)數(shù)據(jù)對(duì)象的時(shí)候,首先從Session一級(jí)緩存中查;查不到,如果配置了二級(jí)緩存,那么從二級(jí)緩存中查;查不到,再查詢數(shù)據(jù)庫(kù),把結(jié)果按照ID放入到緩存。
4) 刪除、更新、增加數(shù)據(jù)的時(shí)候,同時(shí)更新緩存。
Hibernate的二級(jí)緩存策略,是針對(duì)于ID查詢的緩存策略,對(duì)于條件查詢則毫無(wú)作用。為此,Hibernate提供了針對(duì)條件查詢的Query緩存。
Hibernate的Query緩存策略的過(guò)程如下:
1) Hibernate首先根據(jù)這些信息組成一個(gè)Query Key,Query Key包括條件查詢的請(qǐng)求一般信息:SQL, SQL需要的參數(shù),記錄范圍(起始位置rowStart,最大記錄個(gè)數(shù)maxRows),等。
2) Hibernate根據(jù)這個(gè)Query Key到Query緩存中查找對(duì)應(yīng)的結(jié)果列表。如果存在,那么返回這個(gè)結(jié)果列表;如果不存在,查詢數(shù)據(jù)庫(kù),獲取結(jié)果列表,把整個(gè)結(jié)果列表根據(jù)Query Key放入到Query緩存中。
3) Query Key中的SQL涉及到一些表名,如果這些表的任何數(shù)據(jù)發(fā)生修改、刪除、增加等操作,這些相關(guān)的Query Key都要從緩存中清空。
什么樣的數(shù)據(jù)適合存放到第二級(jí)緩存中?
1 很少被修改的數(shù)據(jù)
2 不是很重要的數(shù)據(jù),允許出現(xiàn)偶爾并發(fā)的數(shù)據(jù)
3 不會(huì)被并發(fā)訪問(wèn)的數(shù)據(jù)
4 參考數(shù)據(jù)
不適合存放到第二級(jí)緩存的數(shù)據(jù)?
1 經(jīng)常被修改的數(shù)據(jù)
2 財(cái)務(wù)數(shù)據(jù),絕對(duì)不允許出現(xiàn)并發(fā)
3 與其他應(yīng)用共享的數(shù)據(jù)
無(wú)論何時(shí),當(dāng)給save()、update()或 saveOrUpdate()方法傳遞一個(gè)對(duì)象時(shí),或使用load()、 get()、list()、iterate() 或scroll()方法獲得一個(gè)對(duì)象時(shí), 該對(duì)象都將被加入到Session的內(nèi)部緩存中。
當(dāng)隨后flush()方法被調(diào)用時(shí),對(duì)象的狀態(tài)會(huì)和數(shù)據(jù)庫(kù)取得同步。 如果你不希望此同步操作發(fā)生,或者你正處理大量對(duì)象、需要對(duì)有效管理內(nèi)存時(shí),你可以調(diào)用evict() 方法,從一級(jí)緩存中去掉這些對(duì)象及其集合。如若要把所有的對(duì)象從session緩存中徹底清除,則需要調(diào)用Session.clear(),不過(guò)最好先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
對(duì)于事物管理的確定:
hibernate.cfg.xml :
<hibernate-configuration>
<session-factory>
....
<!-- 設(shè)定事務(wù)管理的工廠類 -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory </property>
</hibernate-configuration>
try {
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
....
tx.commit(); // 必須commit才會(huì)更新資料庫(kù)
} catch(HibernateException e) {
tx.rollback();
}
Postil: 對(duì)于MySQL處理機(jī)制要建立事物表類型的
類型的對(duì)照表:
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 |