標籤:images -- 操作 mit log png 優先 pass lap
一、Hibernate中的對象狀態 1.1、瞬時態(臨時態)
沒有與Hibernate產生關聯
與資料庫中的記錄沒有產生關聯(有關聯就是與資料庫中表的id相對應)
獲得:一般都只直接建立(new)
瞬時態 轉換 持久態
一般操作:save方法、saveOrUpdate
瞬時態 轉換 脫管態
一般操作:通過setId方法設定資料
1.2、持久態
Hibernate有關聯
對象有id
獲得:
查詢操作:get、loat、createQuery、createCriteria 等 獲得都是持久態【】
執行save之後持久態
執行update之後持久態
持久態 轉換 瞬時態
官方規定執行delete() --民間:刪除態
持久態 轉換 脫管態
session沒有記錄
session.close () 關閉
session.clear() 清除所有
session.evict(obj) 清除指定的PO對象
1.3、游離態(脫管態)
沒有與Hibernate產生關聯
對象有ID
獲得:
建立、並設定OID的
通過api獲得
脫管態 轉換 瞬時態
手動去除OID,設定成預設值
脫管態 轉換 持久態
一般操作:update()、saveOrUpdate
1.4、在代碼中去查看三種狀態
1.5、三種狀態的相互轉換 1.5.1、瞬時轉化為持久
注意:如果主鍵建置原則中value是assigned需要自己指定主鍵,不指定會報錯。
1.5.2、瞬時轉化為游離
在資料庫中id=1中已經存在有
1.5.3、持久轉化為瞬時
方式二:
1.5.4、持久轉化為游離
1.5.5、游離轉化為瞬時
1.5.6、游離轉化為持久
1.6、三種狀態有什麼用處?
持久狀態,我們使用Hibernate主要是為了持久化我們的資料.
對於對象的狀態,我們期望我們需要同步到資料庫的資料,都被裝換成持久狀態
持久化狀態特點: Hibernate會自動將持久化狀態物件的變化同步到資料庫中.
二、一級緩衝
又稱為session層級的緩衝。當獲得一次會話(session),hibernate在session中建立多個集合(map),用於存放操作資料(PO對象),為程式最佳化服務,
如果之後需要相應的資料,hibernate優先從session緩衝中擷取,如果有就使用;如果沒有再查詢資料庫。當session關閉時,一級緩衝銷毀。
在Hibernate中存在兩種緩衝:一是線程層級的緩衝(session緩衝)二是進程層級的緩衝(二級緩衝)
緩衝:用來提高效率的
session緩衝:就是session對象中存在的緩衝,緩衝中存在的是(持久化)對象。
2.1、證明session緩衝的存在
我們用圖形來理解:
2.2、一級緩衝快照
在從資料庫取資料時,會將資料一式兩份,一份作為緩衝中的對象,一份作為快照,在session提交時做對比。
快照:與一級緩衝一樣的存放位置,對一級快取資料備份。保證資料庫的資料與 一級緩衝的資料必須一致。如果一級緩衝修改了,
在執行commit提交時,將自動重新整理一級緩衝,執行update語句,將一級緩衝的資料更新到資料庫。
舉例:
我們畫圖來分析一下:
持久化狀態: 本質就是存在緩衝中的對象,就是持久化狀態.
2.3、感受一級緩衝帶來的效率
感受一:
從上面這三行代碼中,我們u1執行需要執行一條sql語句,我們執行得到u2和u3時,發現不會去重新查詢,而是從緩衝中找。
感受二:
從上面代碼還在那個我們知道,第一個u1中會執行select語句。當事務還沒有提交的時候,只會在緩衝中進行。
所以總的只會產生兩條sql語句。
2.4、一級緩衝中的細節問題
問題一:儲存對象時,可以使用save方法和persist方法,他們之間有區別嗎?
沒有區別,功能上是一樣的。但persist(持久) 方法 來自於JPA 介面。而save(儲存) 方法來自於Hibernate。
問題二:HQL查詢是否會使用一級緩衝?
HQL不會使用一級緩衝.
問題三:HQL語句批量查詢時,查詢結果是否會進入緩衝?
查詢結果會放入緩衝中
問題四:SQL查詢 結果會不會放入1級緩衝中?
如果把查詢結果封裝到對象中,對象會放入一級緩衝
問題五:SQL查詢 結果會不會放入1級緩衝中?
沒有把查詢結果封裝到對象中,對象不會放入一級緩衝
問題六:criteria 會將查詢結果放入一級緩衝. 但是查詢不會使用一級緩衝. 與Hql查詢結論一致.
三、session中的其他API
evict()方法:將緩衝中的對象刪除
clear()方法:清空一級緩衝
refresh方法:重新整理,強制重新整理緩衝中的對象 => (可以用來解決緩衝與資料庫資料不同步的問題)
flush方法:對比快照,並提交緩衝對象
import java.util.List;import org.hibernate.Session;import org.junit.Test;import com.itheima.domain.User;import com.itheima.utils.HibernateUtils;//其他API (大部分都是瞭解)public class Demo1 { @Test //1. evict 將緩衝中的對象移除. //2. clear 清空1級緩衝 public void fun1(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u1 = (User) session.get(User.class, 1); session.clear(); User u2 = (User) session.get(User.class, 1); //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 } @Test //3 refresh 重新整理 => 強制重新整理緩衝中的對象 => (可以用來解決緩衝與資料庫資料不同步的問題) public void fun2(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u1 = (User) session.get(User.class, 1); session.refresh(u1); //將緩衝中的對象立刻與資料庫同步,會再發送一個sql語句 //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 } @Test //4 flush 對比快照,並提交緩衝對象 public void fun3(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u1 = (User) session.get(User.class, 1); //u1.setName("zhangsan"); session.flush();// 立刻提交session緩衝中的對象到資料庫 //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 } @Test // 代理主鍵=> native //5.1 aveOrUpdate方法 //saveOrUpdate 可以同時完成儲存或更新操作 //主鍵為空白=>save //主鍵有值=> update public void fun4(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u = new User(); u.setId(99); u.setName("jack"); u.setPassword("1234"); session.saveOrUpdate(u); //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 } // 自然主鍵=> assigned //5 update 與 saveOrUpdate方法 //saveOrUpdate 可以同時完成儲存或更新操作 //主鍵為空白=> 報錯,因為無論是save還是update 都必須指定id //主鍵有值=> 先會根據主鍵查詢資料庫. // 資料庫中存在=> 執行update // 資料庫中不存在=> 執行insert @Test public void fun5(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u = new User(); u.setId(88); u.setName("jack01"); u.setPassword("1234"); session.saveOrUpdate(u); //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 } @Test //在我們使用Hibernate時候,注意要避免出現,兩個相同的ID對象.放入一級緩衝的情況. public void fun6(){ Session session = HibernateUtils.openSession(); session.beginTransaction(); //------------------------------------------------ User u = (User) session.get(User.class, 1);// 持久化,緩衝中存在 session.evict(u); // 游離態,緩衝中不存在 User u2 = (User) session.get(User.class, 1);// 持久化,緩衝中存在 session.update(u); // 將U重新變為持久化狀態,緩衝中存在 //------------------------------------------------ session.getTransaction().commit(); session.close(); // 游離狀態 }}testSessionApi
Hibernate(四)之對象狀態及一級緩衝