天天看點

Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

Hibernate

  • hibernate架構
  • hibernate實體規則
    • 實體内建立的注意事項
    • 主鍵類型
    • 主鍵生成政策generator
  • hibernate中的對象狀态
    • hibernate進階
    • hibernate中的事務
    • hibernate中的批量查詢
  • hibernate多表操作
  • hibernate的多表查詢

hibernate架構

1.什麼是架構

提高我們的開發效率.可以了解成是一個半成品項目.

2.hibernate架構

dao層架構

操作資料庫.

以面向對象的方式操作資料庫.

orm 思想. 對象關系映射. 通過映射檔案配置對象與資料庫中表的關系

O 對象

R 關系型資料庫

M 映射檔案

3.hibernate架構搭建

  1. 導包

    required+驅動包

  2. 準備實體類 以及 orm中繼資料
  3. 建立主配置檔案
  4. 書寫代碼測試

4.配置檔案詳解

  • orm中繼資料(xxx.hbm.xml)
<hibernate-mapping package="">
			<class name table>
				<id name >
					<generator class="">
				</id>
				<property name="" />
           
  • hibernate.cfg.xml
    • 必選配置

      4+1 方言

<!-- 資料庫驅動 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		 <!-- 資料庫url -->
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
		 <!-- 資料庫連接配接使用者名 -->
		<property name="hibernate.connection.username">root</property>
		 <!-- 資料庫連接配接密碼 -->
		<property name="hibernate.connection.password">1234</property>
		<!-- 資料庫方言
		不同的資料庫中,sql文法略有差別. 指定方言可以讓hibernate架構在生成sql語句時.
		針對資料庫的方言生成.
			sql99标準: DDL 定義語言  庫表的增删改查
					  DCL 控制語言  事務 權限
					  DML 操縱語言  增删改查
			注意: MYSQL在選擇方言時,請選擇最短的方言.
		 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
           
  • 可選配置

    顯示sql

    格式化sql

    自動生成表

<!-- 将hibernate生成的sql語句列印到控制台 -->
			<property name="hibernate.show_sql">true</property>
		<!-- 将hibernate生成的sql語句格式化(文法縮進) -->
			<property name="hibernate.format_sql">true</property>
		<!-- 
		## auto schema export  自動導出表結構. 自動建表
		#hibernate.hbm2ddl.auto create		
		自動建表.每次架構運作都會建立新的表.以前表将會被覆寫,表資料會丢失.(開發環境中測試使用)
		#hibernate.hbm2ddl.auto create-drop 
		自動建表.每次架構運作結束都會将所有表删除.(開發環境中測試使用)
		#hibernate.hbm2ddl.auto update(推薦使用) 
		自動生成表.如果已經存在不會再生成.如果表有變動.自動更新表(不會删除任何資料).
		#hibernate.hbm2ddl.auto validate	
		校驗.不自動生成表.每次啟動會校驗資料庫中表是否正确.校驗失敗.
		 -->
			<property name="hibernate.hbm2ddl.auto">update</property>
           
  • 指定隔離級别和orm中繼資料引入
<!-- 指定hibernate操作資料庫時的隔離級别 
			#hibernate.connection.isolation 1|2|4|8		
			0001	1	讀未送出
			0010	2	讀已送出
			0100	4	可重複讀
			1000	8	串行化
		 -->
		 <property name="hibernate.connection.isolation">4</property>
		 <!-- 指定session與目前線程綁定 -->
		 <property name="hibernate.current_session_context_class">thread</property>
		 
		 <!-- 引入orm中繼資料
			路徑書寫: 填寫src下的路徑
		 -->
		<mapping resource="com/dustdawn/entity/Customer.hbm.xml" />
           

5.api詳解

Configuration 讀取配置

sessionFactory 建立session

Session 獲得事務操作對象,以及資料增删改查

Transaction 控制事務

hibernate實體規則

實體内建立的注意事項

  1. 持久化類提供無參數構造
  2. 成員變量私有,提供共有get/set方法通路,需提供屬性
  3. 持久化類中的屬性,因盡量使用包裝類型(不會錯,且值能為null)
  4. 持久化類需要提供oid,與資料庫中的主鍵列對應
  5. 不要用final修飾class(非接口代理,hibernate使用cglib代理生成代理對象,代理對象是繼承被代理對象,如果被final修飾将無法生成代理)

主鍵類型

  • 自然主鍵

    表的業務列中,有某業務列符合,必須有,并且不重複的特征時,該列可以作為主鍵使用

  • 代理主鍵

    表的業務列中,沒有某業務列符合,必須有,并且不重複的特征時,建立一個沒有業務意義的列作為主鍵

主鍵生成政策generator

就是每條記錄錄入時,主鍵的生成規則(7個)

xxx.hbm.xml

< id name=“cust_id” >

< generator class=“native”>< /generator>

< /id>

  • 代理主鍵
    • identity : 主鍵自增.由資料庫來維護主鍵值.錄入時不需要指定主鍵.
      • sequence: Oracle中的主鍵生成政策.
      • increment(了解): 主鍵自增.由hibernate來維護.每次插入前會先查詢表中id最大值.+1作為新主鍵值.
      • hilo(了解): 高低位算法.主鍵自增.由hibernate來維護.開發時不使用.
      • native:hilo+sequence+identity 自動三選一政策.
      • uuid: 産生随機字元串作為主鍵. 主鍵類型必須為string 類型.
  • 自然主鍵
    • assigned:自然主鍵生成政策. hibernate不會管理主鍵值.由開發人員自己錄入.

hibernate中的對象狀态

Session接口是hibernate應用程式提供的操作資料庫的接口,提供了基本的儲存,更新,删除,和加載java對象的方法。Session具有一個緩沖,位于緩存中的對象稱為持久化對象。

  • 瞬時狀态
    • 沒有id,沒有與session關聯(沒有在session緩存中):customer.setCust_name("");
  • 持久化狀态
    • 有id,與session關聯(在session緩存中):session.save(customer);
    • 特點:持久化狀态對象的任何變化自動同步到資料庫中
  • 遊離/托管狀态
    • 有id,沒有與session關聯(沒有在session緩存中):session.close();

      Customer c1 = new Customer();

      c1.setCust_id(1l);

      設定id不存在對應瞬時,存在則遊離

session的save()方法不能了解成儲存,應該了解成将瞬時狀态轉換成持久狀态的方法。

主鍵自增,執行save方法,為了将對象轉換成持久化狀态,必須生成id值,是以需要執行insert語句生成

saveOrUpdate方法将任意對象将對象轉換成持久化對象

==持久化狀态的對象,會在事務送出是,自動同步到資料庫中

hibernate使用原則:将我們希望同步到資料庫的資料,對應的對象轉換成持久化狀态

hibernate進階

一級緩存

  • 緩存:提高效率,hibernate中的一級緩存是為了提高操作資料庫的效率
  • 一級緩存:為了提高效率,session對象中有一個可以存放對象的集合

    查詢時:第一次查詢時,會将對象放入緩存,再次查詢時,會傳回緩存中的,不再查詢資料庫

    修改時:會使用快照對比修改前和修改後對象的屬性差別,隻執行一次修改

  • 提高效率手段1:提高查詢效率
    Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
  • 提高效率手段2:減少不必要的的修改語句發送(快照)
Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

持久化狀态對象其實就是放入session緩存中的對象

hibernate中的事務

Service層

HibernateUtils.getCurrentSession().beginTransaction();

操作事務

HibernateUtils.getCurrentSession().getTransaction().commit();

HibernateUtils.getCurrentSession().getTransaction().rollback();

Dao層

Session session = HibernateUtils.getCurrentSession();

session.get();

  • 事務特性
    • A — 原子性

      事務可以看做資料庫操作的容器,對事務所包裹的操作被認為像實體上的原子,是最小、不可分割的機關,要麼全成功,要麼全失敗

    • C — 一緻性

      事務在送出前後資料總量不應該發生變化(賴以保證的基礎是原子性)

    • I — 隔離性

      多個事務在并發産生的時候,可能會産生一些負面問題(髒讀、不可重複讀、幻讀)

      提供隔離級别解決

    • D — 持久性

      保證事務送出之後,涉及到操作的資料必須被寫入持久化媒體(如硬碟)中

  • 事務并發問題
    • 髒讀

      某事務讀到了另一個事務正在操作但未送出的資料

    • 不可重複讀

      一次事務中兩次連續的讀取到的資料内容不一緻(過程中其他事務修改資料并送出了)

    • 幻/虛讀

      一次事務中兩次連續的讀取到的資料數量不一緻(過程中其他事務增加資料并送出了)

解決方法:

  • 事務的隔離級别

    1)read uncommitted : 讀取尚未送出的資料 :哪個問題都不能解決

    2)read committed:讀取已經送出的資料 :可以解決髒讀 ---- oracle預設的

    3)repeatable read:重讀讀取:可以解決髒讀 和 不可重複讀 —mysql預設的

    4)serializable:串行化:可以解決 髒讀 不可重複讀 和 虛讀—相當于鎖表操作資料隻允許串行,不允許并發

知識點1. 在Hibernate中配置操作資料庫中的隔離級别

<!-- 指定hibernate操作資料庫時的隔離級别 
			#hibernate.connection.isolation 1|2|4|8		
			0001	1	讀未送出
			0010	2	讀已送出
			0100	4	可重複讀
			1000	8	串行化
		 -->
		 <property name="hibernate.connection.isolation">4</property>
		
           

知識點2. 在項目中如何管理事務

  • 在業務開始之前打開事務
  • 業務執行之後送出事務
  • 執行過程中出現異常復原事務
  • 在dao層操作資料庫需要用到session對象,在service層控制事務也是使用session對象完成,要保證dao層和service層使用同一個session

    解決方法

    原理:将session對象綁定到ThreadLocal線程

    調用sessionfactory.getCurrentSession()方法即可獲得與目前線程綁定的session對象

    方法:hibernate.cfg.xml中配置

<!-- 指定session與目前線程綁定 -->
		 <property name="hibernate.current_session_context_class">thread</property>
           

注意1:調用getCurrentSession方法必須配合主配置中的上配置

注意2:通過getCurrentSession方法獲得的session對象,當事務送出時,session會自動關閉,不要手動調用close關閉

hibernate中的批量查詢

  • HQL查詢(多表查詢,但不複雜時使用)

    Hibernate Query Language(Hibernate獨家查詢語言,屬于面向對象的查詢語言)

    HQL語句中,不可能出現任何資料庫相關的資訊的

    • 基本查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 條件查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 分頁查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
  • Criteria查詢(單表查詢)

    Hibernate自創的無語句面向對象查詢

    • 基本查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 條件查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 分頁查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 查詢總記錄數
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
  • 原生SQL查詢(複雜的業務查詢)
    • 基本查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 條件查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 分頁查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

hibernate多表操作

  • 多對一/一對多
    • 關系表達

      表中的表達:外鍵指向一的一方主鍵

      在對象中的表達:使用集合表達,一的一方持有多個多的一方

      使用對象引用一的一方,表達多的一方屬于哪個一的一方

      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 操作
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      <set name="linkMens" cascade="save-update" inverse="true">
      	<!--外鍵列名  -->
      	<key column="lkm_cust_id"></key>
      	<one-to-many class="LinkMan" />
      	</set>
      
      <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
      </many-to-one>
                 
    • 級聯操作
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 關系維護

      在儲存時,兩方都會維護外鍵關系,關系維護兩次造成備援,多餘的維護關系語句顯然是客戶這一端在維護關系(聯系人一端通過外鍵已經維護關系)

      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

      多的一方(LinkMan)不能放棄維護關系,因為外鍵字段就在多的一方

      原則:無論怎麼放棄,總有一方必須要維護關系

      一對多關系中:隻能一的一方放棄維護,多的一方不能放棄維護

      ( 如果客戶放棄維護與聯系人的關系. 維護關系的代碼可以省略

      如果執行删除主表操作時,主表選擇維護關系,可以解除與從表的外鍵限制,從表外鍵置空,記錄不變,級聯操作為delete時,會将兩表一同删除)

  • 多對多
    • 關系表達

      使用中間表,至少兩列,都是外鍵列,分别引用兩張表的主鍵

      兩方都使用集合來表達擁有多個對方

    • 操作

      orm中繼資料xxx.hbm.xml

      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

      将來在開發中,如果遇到多對多關系.一定要選擇一方放棄維護關系.

      一般誰來放棄要看業務方向. 例如錄入員工時,需要為員工指定所屬角色.

      那麼業務方向就是由員工維護角色. 角色不需要維護與員工關系.角色放棄維護

    • 級聯操作
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

hibernate的多表查詢

  • 查詢總結
    • oid查詢—get方法

      session.get(實體類.class,id)

    • 對象屬性導航查詢
    • HQL
      • 基礎文法
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 排序
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 條件
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 分頁
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 聚合
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 投影
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 多表查詢

        内連接配接(迫切fetch封裝成一個對象) inner join(fetch)

        外連接配接

      1. 左外(迫切) left join(fetch)
      2. 右外(迫切)right join(fetch)
    • Criteria
      • 基本文法
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 離線查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 原生SQL
  • 查詢優化
    • 類級别查詢

      session.get()方法:沒有任何政策,調用即立即查詢資料庫加載資料

    session.load()方法(true:預設延遲加載):是在執行時,不發送任何sql語句,傳回一個對象,使用該對象時,才執行查詢(orm中繼資料檔案中class元素上配置lazy屬性來控制:

    < class name=“Customer” table=“cst_customer” lazy=“true”>)

    延遲加載:僅僅獲得沒有使用,不會查詢,在使用時才進行查詢
      
      lazy(預設值):true,查詢類時,會傳回代理對象(帶$符号)不去查詢,而在使用屬性時,調用代理對象增強的方法,根據關聯的session查詢資料庫加載資料
               
    結論:為了提高效率.建議使用延遲加載(懶加載),優化查詢
    • 關聯級别查詢

      set元素中配置

      對象屬性導航:Customer的屬性getLinkMen導航另一個對象

      • 集合政策(一的一方Customer,取LinkMan)
        • 延遲加載&抓取政策

          extra:如果隻獲得集合的size,隻查詢集合的size(count語句),不會列印資料

          fetch為join時,類級别加載lazy屬性失效

          Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
      • 關聯屬性政策(多的一方LInkMan,加載Customer)
        Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
        結論:為了提高效率.fetch的選擇上應選擇select, lazy的取值應選擇 true. 全部使用預設值.
      • no-session問題解決

        采用上結論懶加載時,傳回頁面是為代理對象,到達頁面時service層執行完畢,session關閉,會出現懶加載初始化缺少session對象的情況

      解決方法:通過Filter擴大session的作用範圍
      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢
    • 批量抓取

      周遊每個客戶都要用sql語句查詢聯系人

      Hibernate學習筆記hibernate架構hibernate實體規則hibernate中的對象狀态hibernate多表操作hibernate的多表查詢

繼續閱讀