1. 程式人生 > >Hibernate Session詳解

Hibernate Session詳解

Session介面是hibernate中的核心介面,它不是javaweb應用中的HttpSession介面

Session概述 

Session介面是Hibernate嚮應用程式提供的操縱資料庫的主要介面,它提供了實現基本的儲存、更新、刪除和載入java物件的方法Session快取

 Session 具有一個快取, 位於快取中的物件稱為持久化物件, 它和資料庫中的相關記錄對應。Session 能夠在某些時間點, 按照快取中物件的變化來執行相關的 SQL 語句, 來同步更新資料庫, 這一過程被稱為重新整理快取(flush)。也叫一級快取


Session 介面的實現中包含一系列的

Java 集合, 這些 Java 集合構成了 Session 快取。 只要 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 生成器生成

OID(Object ID), 那麼當呼叫 Session save() 方法儲存物件時, 會立即執行向資料庫插入該實體的 insert 語句。

 

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() 方法.