1.1 持久化類的編寫規則 1.1.1 什麼是持久化類? 持久化類 : 與表建立了映射關係的實體類,就可以稱之為持久化類. 持久化類 = Java類 + 映射文件. 1.1.2 持久化類的編寫規則 (1): 提供無參數的構造方法 (2): 類中的成員都是私有的private (3): 對私有屬性提供... ...
1.1 持久化類的編寫規則 1.1.1 什麼是持久化類? 持久化類 : 與表建立了映射關係的實體類,就可以稱之為持久化類. 持久化類 = Java類 + 映射文件. 1.1.2 持久化類的編寫規則 (1): 提供無參數的構造方法 (2): 類中的成員都是私有的private (3): 對私有屬性提供get/set方法 (4): 屬性儘量使用包裝類類型 : 預設值不同的,包裝類預設值null,基本數據類型預設0. (5): 持久化類不要使用final進行修飾 : 使用final修飾,延遲載入失效,變為立即載入. (6): 類中需要提供標識屬性(OID), 與表中主鍵建立映射關係 : Hibernate根據標識屬性來判斷對象是否是同一個的. 持久化類就是一個特殊的javabean Hibernate 中實體類的標識屬性 : Object Identifie 簡稱OID屬性 就是配置文件中對應主鍵的那個實體類屬性. 作用: 讓Hibernate來區分對象是否是同一個. 如果多個對象的標識屬性值相同,hibernate會認為是同一個對象,存儲數據會報錯. OID屬性都是交給hibernate來維護: 好處 : 不會用重覆相同的OID屬性. 不用自己去寫代碼保證非空唯一. 1.2 Hibernate 主鍵生成策略: 1.2.1 區分自然主鍵和代理主鍵 自然主鍵 : 創建表的時候,使用的是實體中的自身屬性作為表的主鍵. 例如 : 創建一張人員表,可以用自生的身份證號(唯一的不可重覆)作為主鍵. 代理主鍵 : 創建表的時候,使用的不是實體中的自身的屬性作為主鍵,創建一個不相關的欄位作為主鍵. 例如 : 創建一張人員表,不使用自生的身份證號(唯一的不可重覆的)作為主鍵,用另外創建一個id作為主鍵. 儘量使用代理主鍵.如果選用自然主鍵,當主鍵需要參與到業務邏輯中,有可能需要改變很多的設計和代碼. 1.2.2 的主鍵生成策略 主鍵不應該由用戶自己維護,應該統一管理,那麼Hibernate就提供了主鍵統一管理的方式: 主鍵生成策略. increment : 自動增長, 是hibernate中提供一種自動增長方式,不是資料庫中的自動增長.(適用於short,int,long類型的主鍵) 首先使用 select max(cust_id) from cust_customer;將這個最大值 + 1 作為下一條記錄的主鍵. 對於併發訪問資料庫不適用. identity : 自動增長, 適用於short,int,long類型的主鍵,使用的是資料庫自動增長機制.不是所有資料庫都支持自動增長,比如Oracle沒有自動增長. sequence : 序列, 適用於short,int,long類型的主鍵,使用序列方式完成主鍵的生成.必須是支持序列的方式的資料庫.Oracle的自動增長. native : 本地策略,根據底層的資料庫不同,自動選擇使用identity還是sequence. uuid : 隨機字元串,適用於字元串類型的主鍵. assigned : Hibernate不維護主鍵,開發人員需要手動設置主鍵. 總結: 以後如果是針對是數值型,選擇用native,如果是varchar類型,可以選擇用uuid 但是也可以不用hibernate維護,自己在程式中手動設定唯一非空(assigned) 1.3 持久化類的三種狀態 1.3.1 Hibernate 的持久化類的三種狀態. Hibernate框架為了更好管理持久化類,將持久化類分成了三種狀態. 瞬時態 : 沒有持久化標識OID,沒有被session操作管理. 持久態 : 有持久化標識OID,已經被session操作管理. 脫管態(離線態) : 有持久化標識OID,沒有被session操作管理. 1.3.2 區分持久化類的三種狀態 public void demo1() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); //瞬時態 : 沒有持久化標識OID,沒有被session管理. Customer customer = new Customer(); customer.setCust_name("黃天華"); //持久態 : 有持久化標識OID,已經被session管理 Serializable id = session.save(customer); System.out.println(id); transaction.commit(); session.close(); //脫管態 : 有持久化標識OID,沒有被session管理. System.out.println(customer.getCust_name()); } 1.3.3 三種狀態的轉換(面試題) 瞬時態 : 沒有持久化標識OID,沒有被session管理. 獲得: Customer customer = new Customer(); 狀態轉換: 瞬時 --> 持久 : save,saveOrUpdate 瞬時 --> 托管 : customer.setCust_id(1L); 持久態 : 有持久化標識OID,已經被session管理 獲得 : 只要是涉及到查詢方法都是直接獲得持久態對象. Customer customer = session.get(Customer.class,1L); 狀態轉換 持久 --> 托管 : close 持久 --> 瞬時 : delete 脫管態 : 有持久化標識OID,沒有被session管理 獲得 Customer customer = new Customer(); customer.setCust_id(1L); 狀態轉換 : 托管 --> 持久 : save,update,saveOrUpdate 托管 --> 瞬時 : customer.setCust_id(null) 持久態 : 只要涉及到查詢返回的就都是持久態類的持久態對象. 特點 : 如果持久態對象修改完屬性,不需要執行更新操作,會自動更新資料庫數據. 1.3.4 持久態可以自動更新資料庫 public void demo2() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); //獲得持久態對象 Customer customer = session.get(Customer.class,1L); customer.setCust_name("王寶強"); //session.update(customer);//沒有手動調用update方法,但是也可以更新資料庫 transaction.commit(); session.close(); } 1.4 Hibernate的一級緩存 1.4.1 緩存的概述 1.4.2 Hibernate 的一級概述: Hibernate框架本身的性能不是很好,但是Hibernate提供了很多的性能優化的手動,比如,緩存. Hibernate框架提供了兩個級別的緩存: 一級緩存: 稱為Session級別的緩存.因為一級緩存的生命周期與session一致的.自帶的,不可卸載的.(由Session中一系列的Java集合構成的) 二級緩存: 稱為SessionFactory級別的緩存.需要進行配置的緩存的插件.預設不開啟的.ehche == redis ps : 除了刪除,增改查和資料庫打完交道,都會往一級緩存中留一份. 但是session只要關閉,一級緩存的數據全部清空. 原因: 一級緩存的存在 原理: session.get(Customer.class, 1L) // 去資料庫查詢,查完了之後放在一級緩存中 一級緩存 存儲區 放一份 快照區 備份一份 ct.setCust_name("rose1234"); // 去一級緩衝中的存儲區修改了內容,但是快照區不修改 一級緩存 存儲區 修改了 快照區 以前的 tx.commit(); // 去一級緩存中,將存儲區和快照區的數據都拿出來對比 一致: 什麼都不做 不一致: 自動發送update語句做數據的數據更新 1.4.3 證明一級緩存的存在: public void demo1() { Session session = HibernateUtils.ipenSession(); Thransaction transaction = session.beginTransaction(); Customer customer = new Customer(); customer.setCust_name("好強"); Serializable id = session.save(customer); session.get(Customer.classmid);//沒有發燒SQL語句. Customer customer1 = session.get(Customer.class,1L);//發送SQL語句去查詢 System.out.println(customer1); Customer customer2 = session.get(Customer.class,1L);//不發送SQL語句 System.out.println(customer2); transaction.commit(); session.close(); } 一級緩存區裡面有緩存區和快照區,當把數據重新設置以後,更新緩存區,進行commit提交,會對比一級緩衝區裡面的緩存區和快照區是否一致, 如果一致,則不更新資料庫;如果不一致,則重新存儲到快照區,並更新資料庫. 1.4.5 一級緩存的管理的方法 : 清空一級緩存的數據 clear,evict,close 管理一級緩存的相關的方法. clear 可以清空一級緩存的所有數據. evict 可以清空一級緩存的某一個對象的數據. 1.5 Session的綁定(ThreadLocal) 1.5.1 Hibernate中設置與當前線程綁定的session的使用 <!-- 設置與當前線程綁定的session --> <property name="hibernate.current_session_context_class">thread</property> 1.6 Hibernate的其他的API 在hibernate中,查詢批量數據的方式: Query方式 : 如果是使用這種方式做查詢,又被稱作為HQL查詢. Criteria方式 : 如果是使用這種方式做查詢,又被稱作為QBC查詢. 1.6.1 Query : HQL查詢 接收一個HQL進行查詢 : HQL-Hibernate Query Language Hibernate查詢語言,與SQL語言語法很相似的一個語言.面向對象.Query介面,HQL面向對象的查詢.查詢都是對象. @Test /** * Query介面 * HQL面向對象的查詢.查詢都是對象 */ public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 查詢全部客戶信息: /*Query query = session.createQuery("from Customer"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); }*/ // 條件查詢 /*Query query = session.createQuery("from Customer where cust_name like ?"); // 設置參數 query.setParameter(0, "郝%"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); }*/ // 分頁查詢: Query query = session.createQuery("from Customer"); // 從哪開始的 query.setFirstResult(3); // 每頁顯示記錄數 query.setMaxResults(3); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); } transaction.commit(); } 1.6.2 Criteria : QBC查詢 QBC-Query By Criteria 條件查詢.更加面向對象化查詢語言. @Test /** * QBC查詢:Query By Criteria */ public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 查詢全部: /* Criteria criteria = session.createCriteria(Customer.class); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); }*/ // 條件查詢 /** * == eq * > gt * >= ge * < lt * <= le * <> ne * in in * like like * */ /*Criteria criteria = session.createCriteria(Customer.class); // criteria.add(Restrictions.eq("cust_name", "郝天一")); criteria.add(Restrictions.like("cust_name", "郝%")); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); }*/ // 分頁查詢 Criteria criteria = session.createCriteria(Customer.class); criteria.setFirstResult(3); criteria.setMaxResults(3); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } transaction.commit(); }