Hibernate Session詳解
Session介面是hibernate中的核心介面,它不是javaweb應用中的HttpSession介面
Session概述
Session介面是Hibernate嚮應用程式提供的操縱資料庫的主要介面,它提供了實現基本的儲存、更新、刪除和載入java物件的方法Session快取
Session 具有一個快取, 位於快取中的物件稱為持久化物件, 它和資料庫中的相關記錄對應。Session 能夠在某些時間點, 按照快取中物件的變化來執行相關的 SQL 語句, 來同步更新資料庫, 這一過程被稱為重新整理快取(flush)。也叫一級快取。
在 Session 介面的實現中包含一系列的
Session 快取可減少 Hibernate 應用程式訪問資料庫的頻率。
什麼是session的生命週期?
session = sessionFactory.openSession();
session.close();
Session快取示例:
public class HibernateTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; /** * 初始化Hibernate */ @Before public void init(){ /** * 方法一:我們使用Configuration來加建立SessionFactory */ // Configuration cfg = new Configuration().configure("hibernate.cfg.xml"); // sessionFactory = cfg.buildSessionFactory(); /** * 方法二: 利用服務註冊的方式建立sessionFactory */ final StandardServiceRegistry registry = new StandardServiceRegistryBuilder() .configure() .build(); sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); } /** * 關閉Hibernate連線 */ @After public void destory(){ transaction.commit(); session.close(); sessionFactory.close(); } /** * session快取的示例 * 只向資料庫傳送一條SQL語句。user和user1均對應的是user物件。 */ @Test public void testSessionCache(){ /** * select * from user where id=1; */ User user = session.get(User.class, 1); System.out.println(user); User user1 = session.get(User.class, 1); System.out.println(user1); System.out.println(user == user1); }}
操作Session快取的方法
flush方法
Session 按照快取中物件的屬性變化來同步更新資料庫
預設情況下 Session 在以下時間點重新整理快取:
1:顯式呼叫 Session 的 flush() 方法
2:當應用程式呼叫 Transaction 的 commit()方法的時, 該方法先 flush ,然後在向資料庫提交事務
3:當應用程式執行一些查詢(HQL, Criteria)操作時,如果快取中持久化物件的屬性已經發生了變化,會先 flush 快取,以保證查詢結果能夠反映持久化物件的最新狀態
flush 快取的例外情況:
如果物件使用 native 生成器生成
commit() 和 flush() 方法的區別:
flush 執行一系列 sql 語句,但不提交事務;commit 方法先呼叫flush() 方法,然後提交事務. 意味著提交事務意味著對資料庫操作永久儲存下來。
@Test
public void testSessionFlush(){
User user = session.get(User.class, 1);
user.setName("南城同學");
session.flush();
// User user1 = (User) session.createCriteria(User.class).uniqueResult();
// System.out.println(user1);
}
reflesh方法
refresh()會強制傳送select語句,以使session快取中的物件狀態和資料庫表中的記錄保持一致
@Test
public void testRefresh(){
User user = session.get(User.class, 1);
System.out.println(user);
session.refresh(user);
System.out.println(user);
}
clear方法
清除session快取
@Test
public void testClear(){
User user = session.get(User.class, 1);
session.clear();
User user1 = session.get(User.class, 1);
System.out.println(user == user1);
}
那麼最後的比較將是false
持久化狀態
站在持久化的角度, Hibernate 把物件分為 4 種狀態: 持久化狀態, 臨時狀態, 遊離狀態, 刪除狀態. Session 的特定方法能使物件從一個狀態轉換到另一個狀態。
臨時物件(Transient):
在使用代理主鍵的情況下, OID 通常為 null
不處於 Session 的快取中
在資料庫中沒有對應的記錄
@Test
public void testSave(){
User user = new User();
user.setName("Tom_iii");
user.setAccount(new BigDecimal(600));
user.setCreateTime(new Date());
System.out.println(user); //臨時物件
session.save(user);
System.out.println(user); //持久化物件
/**
* 持久化物件的ID是不能被修改的
*/
// user.setId(7);
}
持久化物件(也叫”託管”)(Persist):
OID 不為 null
位於 Session 快取中
若在資料庫中已經有和其對應的記錄, 持久化物件和資料庫中的相關記錄對應
Session 在 flush 快取時, 會根據持久化物件的屬性變化, 來同步更新資料庫
在同一個 Session 例項的快取中, 資料庫表中的每條記錄只對應唯一的持久化物件
/**
* persist() : 也會執行insert語句
*/
@Test
public void testPersist(){
User user = new User();
user.setName("Tom");
user.setAccount(new BigDecimal(600));
user.setCreateTime(new Date());
System.out.println(user); //臨時物件
session.persist(user);
System.out.println(user); //持久化物件
}
刪除物件(Removed)
在資料庫中沒有和其 OID 對應的記錄
不再處於 Session 快取中
一般情況下, 應用程式不該再使用被刪除的物件
@Test
public void testDelete(){
User user = session.get(User.class, 4);
session.delete(user);
System.out.println(user);
}
遊離物件(也叫”脫管”) (Detached):
OID 不為 null
不再處於 Session 快取中
一般情況需下, 遊離物件是由持久化物件轉變過來的, 因此在資料庫中可能還存在與它對應的記錄
close()、commit()、clear()
Session的常用方法
Save()方法
Save()方法是用來儲存持久化物件,進而在資料庫中新增一條資料的方法。
Session 的 save() 方法使一個臨時物件轉變為持久化物件
Session 的 save() 方法完成以下操作:
把 user 物件加入到 Session 快取中, 使它進入持久化狀態
計劃執行一條 insert 語句:在 flush 快取的時候
Hibernate 通過持久化物件的 OID 來維持它和資料庫相關記錄的對應關係. 當 user 物件處於持久化狀態時, 不允許程式隨意修改它的 ID
persist() 和 save() 區別:
當對一個 OID 不為 Null 的物件執行 save() 方法時, 會把該物件以一個新的 oid 儲存到資料庫中; 但執行 persist() 方法時會丟擲一個異常
Get()和load()方法
都可以根據跟定的 OID 從資料庫中載入一個持久化物件
區別:
當資料庫中不存在與 OID 對應的記錄時, load() 方法丟擲 ObjectNotFoundException 異常, 而 get() 方法返回 null
兩者採用不同的延遲檢索策略:load 方法支援延遲載入策略。而 get 不支援。
Update()方法
Session 的 update() 方法使一個遊離物件轉變為持久化物件, 並且計劃執行一條 update 語句.
當 update() 方法關聯一個遊離物件時, 如果在 Session 的快取中已經存在相同 OID 的持久化物件, 會丟擲異常
當 update() 方法關聯一個遊離物件時, 如果在資料庫中不存在相應的記錄, 也會丟擲異常.
1.3.4 saveOrUpdate()方法
Session 的 saveOrUpdate() 方法同時包含了 save() 與 update() 方法的功能
1.3.5 Delete()方法
Session 的 delete() 方法既可以刪除一個遊離物件, 也可以刪除一個持久化物件
Session 的 delete() 方法處理過程
計劃執行一條 delete 語句
把物件從 Session 快取中刪除, 該物件進入刪除狀態.
Hibernate呼叫儲存過程
Work 介面: 直接通過 JDBC API 來訪問資料庫的操作
Session 的 doWork(Work) 方法用於執行 Work 物件指定的操作, 即呼叫 Work 物件的 execute() 方法. Session 會把當前使用的資料庫連線傳遞給 execute() 方法.