先看一個例子:
假設我的工程中有個與user類(實體類,與數據庫映射),userDao(繼承自 AbstractHibernateDao),userService。在userService中運行這段代碼:
void saveUser(user us){
//設us中name屬性爲a
userDao.save(us);
us.setName("b");
}
運行後數據庫表中user表的name屬性變爲了”b”,新手的我覺得很奇怪,明明我修改us後沒有對它進行保存,爲什麼會自動保存在數據庫表中?
後來上網查找,發現了個hibernate緩存機制這個東西。
先介紹一下hibernate緩存機制,摘自
一、why(爲什麼要用Hibernate緩存?)
Hibernate是一個持久層框架,經常訪問物理數據庫。
爲了降低應用程序對物理數據源訪問的頻次,從而提高應用程序的運行性能。
緩存內的數據是對物理數據源中的數據的複製,應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。
看到介紹,就基本明白了剛剛問題發生的原因,我在save(us)時hibernate並沒有即時叫數據提交至數據庫中,而是放入緩存,而us.setName(“b”)運行修改了緩存中的us對象,而等事務結束後,再將緩存的數據存儲至數據庫中,如果想即時存儲,應調用session.flush()方法,把緩存的數據存入數據庫中。
摘抄點源博客的東西:
緩存有Session緩存和SessionFactory緩存,Session緩存是默認加載使用的,SessionFactory是一個可配置的插件。
緩存的使用:
1. 一級緩存的管理:
evit(Object obj) 將指定的持久化對象從一級緩存中清除,釋放對象所佔用的內存資源,指定對象從持久化狀態變爲脫管狀態,從而成爲遊離對象。
clear() 將一級緩存中的所有持久化對象清除,釋放其佔用的內存資源。
contains(Object obj) 判斷指定的對象是否存在於一級緩存中。
flush() 刷新一級緩存區的內容,使之與數據庫數據保持同步。
2.一級緩存應用: save()。當session對象調用save()方法保存一個對象後,該對象會被放入到session的緩存中。 get()和load()。當session對象調用get()或load()方法從數據庫取出一個對象後,該對象也會被放入到session的緩存中。 使用HQL和QBC等從數據庫中查詢數據。
3.二級緩存的管理:
evict(Class arg0, Serializable arg1)將某個類的指定ID的持久化對象從二級緩存中清除,釋放對象所佔用的資源。
sessionFactory.evict(Customer.class, new Integer(1));
evict(Class arg0) 將指定類的所有持久化對象從二級緩存中清除,釋放其佔用的內存資源。
sessionFactory.evict(Customer.class);
evictCollection(String arg0) 將指定類的所有持久化對象的指定集合從二級緩存中清除,釋放其佔用的內存資源。
sessionFactory.evictCollection(“Customer.orders”);
4.二級緩存的配置
常用的二級緩存插件
EHCache org.hibernate.cache.EhCacheProvider
OSCache org.hibernate.cache.OSCacheProvider
SwarmCahe org.hibernate.cache.SwarmCacheProvider
JBossCache org.hibernate.cache.TreeCacheProvider