session對象是操做數據庫的主要接口,能夠對數據庫進行保存、更新和刪除等一系列的操做,而且能夠將數據庫中的數據加載到java對象中。java
session對象中有一個緩存,是session級別的,也稱之爲一級緩存。緩存中存儲的java對象被稱之爲持久化對象。持久化對象和數據庫中的相關記錄相互對應。sql
看一段代碼:
數據庫
private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void onLoad() { // 0.建立configuration對象,該對象保存着hibernate的配置信息和對象關係映射的信息。 Configuration cfg = new Configuration().configure(); // 1.建立sessionfactory對象 StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()); StandardServiceRegistry registry = builder.build(); sessionFactory = cfg.buildSessionFactory(registry); // 2.建立session對象 session = sessionFactory.openSession(); // 3.開始事務 transaction = session.beginTransaction(); } @After public void onUnLoad() { // 1.提交事務 transaction.commit(); // 2.關閉session對象 session.close(); // 3.關閉sessionfactory對象 sessionFactory.close(); } @Test public void test() { User user = (User)session.load(User.class, 1); System.out.println(user); // 第二次get時,是從session cache中得到的。 User user2 = (User)session.load(User.class, 1); System.out.println(user2); }
能夠看到從數據庫中查詢了2次user對象,只輸出了一條sql語句。第二次的get操做其實是從緩存中得到的user對象,並無從對數據庫進行select查詢。緩存減小了對數據庫的操做。
緩存
緩存與數據庫之間能夠經過某些方法互相同步,session能夠提取緩存中的對象向數據庫進行操做,也能夠將提取數據庫中的記錄來更新緩存中的對象。還能夠對session緩存進行清空。session
經常使用的操做session緩存的方法有3個,它們分別是:app
flush測試
當調用flush方法時,session將保證緩存中的對象與數據表中的記錄一致。也就是說,若緩存中的對象與數據庫表中的記錄不一致,則會發送update語句更新數據庫。ui
若不顯示調用flush方法,當事務進行commit的時候會自動的調用一次flush方法。hibernate
固然也有例外,在同一個事務中使用QBC或HQL語句也會隱士調用一次flush方法。
code
refresh
當調用refresh方法時,其實與flush大體相反。若緩存中的對象與數據庫表中的記錄不一致,則會發送一個select語句來更新session緩存中的對象。
clear
當調用clear的時候,將清空session緩存中的對象。
進行一些測試,來測試一下這幾個方法,首先是flush方法:
@Test public void testSessionFlush() { // 從數據庫中加載一個對象。 User user = (User)session.get(User.class, 1); user.setName("Kobe"); System.out.println(user); }
數據庫中的保存的Name是"Jack"這個值,get到User對象後,進行一次set,而後commit後會發現生成了一條update語句,數據庫中的值也改變了,這就是flush方法起到的做用,控制檯輸出以下圖:
接下來測試一下refresh方法,寫一段代碼:
@Test public void testSessionRefresh() { User user = (User)session.get(User.class, 1); System.out.println(user); session.refresh(user); User user2 = (User)session.get(User.class, 1); System.out.println(user); }
在session.refresh(user)處打一個短點,在程序暫停後,去數據庫中手動修改name字段的值,在調用refresh方法後看看是否數據庫的值會更新緩存中對象的值,操做過程以下:
程序運行到refresh方法以前,進行一次get,而且進行了輸出。能夠看到控制檯輸出了select和user的值。以後進入斷點等待繼續。
手動修改了數據庫中name字段的值,將"Kobe"改爲了"Mark"。
斷點向下一步,執行了refresh,能夠看到控制檯又輸出了一條select語句。說明對手動修改了數據庫中的數據後,與session緩存中的對象不一致了。須要獲取數據庫中的數據對持久化對象進行覆蓋。因而執行了一次select語句。
最後輸出結構,這裏能夠看到雖然執行了select語句,可是並無改變持久化對象中的數據。這是因爲hibernate的事務隔離機制致使的。一共有4個隔離級別,分別是:
READ UNCOMMITED = 1
READ COMMITED = 2
REPEATABLE READ = 4
SERIALIZEABLE = 8
能夠在配置文件中將隔離級別hibernate.connection.isolation設置成2,這樣refresh就會有預期的效果。
<!-- 設置hibernate的事務隔離機制 --> <property name="hibernate.connection.isolation">2</property>
設置後在進行一次測試,結果以下:
當改變隔離級別後,先修改數據庫的值,在調用refresh方法,則會當即更新持久化對象。
最後測試一下clear方法,該方法會清空session的緩衝區:
@Test public void testSessionClear() { User user = (User)session.get(User.class, 1); session.clear(); User user2 = (User)session.get(User.class, 1); }
最初測試session緩存時,在一個事務中第二次調用get方法加載同一個對象,不會發送select語句到數據庫進行查詢。而在第二次調用get方法前,調用一次clear方法,則會清空session緩衝區中的持久化對象,在次調用get又須要到數據庫進行select操做,控制檯輸出的sql以下:
能夠看到有兩個select語句被打印,證實了clear會清空緩衝區中的持久化對象。
以上就是經常使用的操做session緩衝區的三個方法的測試。