hibernate相關知識的總結

Hibernate是什麼
 面向java環境的對象/關係數據庫映射工具。
1.開源的持久層框架.
2.ORM(Object/Relational Mapping)映射工具,建立面向對象的域模型和關係數據模型之間的映射.
3.連接java應用和數據庫的中間件.
4.對JDBC進行封裝,負責java對象的持久化.
5.在分層結構中處於持久化層,封裝對數據庫的訪問細節,
  使業務邏輯層更專注於實現業務邏輯
爲什麼要用Hibernate 
     1、Hibernate對JDBC訪問數據庫的代碼做了封裝,大大簡化
          了數據訪問層繁瑣的重複性代碼。  ?2、Hibernate是一個基於jdbc的主流持久化框架,是一個優秀
           的orm實現,它很大程度的簡化了dao層編碼工作。  ?3、Hibernate使用java的反射機制,而不是字節碼增強程序類實現
           透明性  ?4、Hibernate的性能非常好,因爲它是一個輕量級框架。映射的靈
           活性很出色。它支持很多關係型數據庫,從一對一到多對多的各
           種複雜關係。  

使用jdbc的問題:
1.操作數據相對繁瑣
2.數據庫字段發生變化時,對應sql語句都要發生變化,不利於後期維護
解決問題:封裝(hibernate)
配置文件(將javabean與數據庫表進行關聯) 放到與Customer類同級的目錄下,並且名稱一樣
Customer.hbm.xml
<hibernate-mapping>
 <!--class:持久化類javabean與表的映射-->
 <class name="cn.itcast.Customer" table="customer">
  <!--id:用來映射主鍵ID-->
  <id name="id"  type="integer">
   <column name="id"></column>
   <!--gererator:主鍵生成策略-->
   <gererator class="increment"/>
  </id>
  <!--type:表示hibernate的數據類型,用來關聯java的數據類型和數據庫的數據類型-->
  <property name="name" column="name" type="string">
  ...
 </class>
</hibernate-mapping>
配置文件(配置連接數據庫基本信息)
hibernate.cfg.xml
<hibernate-configration>
 <sessionFactory>
  <!--基本配置-->
  <property name="hibernate.connection.driverClass">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/database?useUnicode=true&amp;characterEncoding=utf8</property>
  <property name="hibernate.connection.username">root</property>
  <property name="hibernate.connection.password">root</property>
  <!--方言-->
  <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
  <!--
   自動將配置文件.hbm.xml的配置信息關聯數據庫表
   create:表不存在時創建,存在時先刪再創建,然後添加數據
   none:追加數據,不能創建表
   update:表不存在時創建,存在時追加數據
  -->
  <property name="hibernate.hbm2ddl.auto">update</property>
  <!--是否顯示sql語句-->
  <property name="hibernate.show_sql">true</property>
  <!--是否對sql語句格式化-->
  <property name="hibernate.format_sql">true</property>
 </sessionFactory>
</hibernate-configration>

加載配置文件:
Configuration configuration = new Configuration();
1.加載hibernate.cfg.xml
configuration.configure();//默認加載類路徑下文件
configuration.configure("cn/itcast/../hibernate.cfg.xml");
2.加載Customer.hbm.xml  要求配置文件和類放置到同一個目錄下,並且名稱一致
(1)configuration.addClass(Customer.class);
(2)configuration.addResource("cn/itcast/../Customer.hbm.xml");
(3)使用配置文件加載,在hibernate.cfg.xml中配置,項目中使用最多
   <mapping resource="cn/itcast/../Customer.hbm.xml">

hibernate與jdbc對比:
hibernate:SessionFactory工廠(SessionFactory)、創建多個Session(Session)、使用Session來操作數據庫(CURD)
jdbc:連接池(DataSource)、多個連接(Connection)、使用Connection來操作數據庫(CURD)

hibernate基本配置:
1.使用hibernate更加面向對象(使用對象操作數據庫),對DAO層封裝,也就是對JDBC的封裝
2.建立工程
3.導入相應的jar包
4.建立一個持久化的javabean
5.建立Xxx.hbm.xml,用來映射持久化對象與數據庫表的對應關係,規範在hibernate核心包下org.hibernate.hibernate-mapping-3.0.dtd
6.建立連接數據庫信息的配置文件hibernate.cfg.xml,該文件放置到src目錄下,規範在hibernate核心包下org.hibernate.hibernate-  configuration-3.0.dtd
7.測試操作數據庫的CURD
Hibernate的運行過程如下:
1、應用程序先調用Configuration類,該類讀取Hibernate配置文件及映射文件中的信息,
2、並用這些信息生成一個SessionFactory對象,
3、然後從SessionFactory對象生成一個Session對象,
4、並用Session對象生成Transaction對象;
    A、可通過Session對象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法對PO進行加載、保存、更新、刪除、等操作;
    B、在查詢的情況下,可通過Session對象生成一個Query對象,然後利用Query對象執行查詢操作;如果沒有異常,Transaction對象將提交這些操作到數據庫中。

SessionFactory接口:SessionFactory負責維護Hibernate的二級緩存;SessionFactory是生成Session的工廠;是線程安全的

Session接口:Session是應用程序與數據庫之間交互操作的一個單線程對象,是 Hibernate 運作的中心,所有持久化對象必須在 session 的管理下纔可以進行持久化操作。此對象的生命週期很短。Session 對象有一個一級緩存,顯式執行 flush 之前,所有的持久層操作的數據都緩存在 session 對象處。相當於 JDBC 中的 Connection。是線程不安全的。
session的一級緩存:當使用get或者load方法通過OID進行查詢數據庫的時候,會將查詢結果放到session的一級緩存中,如果使用同一個OID再次查詢時,會先到session的一級緩存中查找是否有相同的OID對象,如果有則直接讀取,不再查詢數據庫;如果沒有則查詢數據庫,並將查詢結果放到session的一級緩存中。當session關閉時,一級緩存數據將不存在。

session快照
commit:先清理session的一級緩存,讓緩存中的數據與數據庫同步,然後再提交事務。
當使用get或者load方法通過OID進行查詢數據庫的時候,會將查詢結果放到session的一級緩存中,同時將數據產生(複製)一份快照,當修改session一級緩存中的數據時,並且執行commit()或者s.flush(),表示清理session的一級緩存,此時hibernate會使用OID查找快照中對應的OID對象的數據,然後比對,如果2個OID對象一樣,不會執行update語句,如果2個OID對象不一樣,會執行update語句。

主鍵生成策略(表示符生成器):
increment:由Hibernate以遞增的方式爲代理主鍵賦值
Hibernate會先讀取表中的主鍵的最大值,而接下來向表中插入記錄時, 就在 max(id) 的基礎上遞增,增量爲1(帶走加1:多線程有併發問題)
不依賴於底層數據庫系統,適合所有的數據庫系統;適用於只有單個Hibernate應用進程訪問同一個數據庫的場合;
OID必須爲long,int或short

identity:底層數據庫把主鍵定義爲自動增長字段類型(加1帶走:多線程沒有併發問題)
底層數據庫系統必須支持自動增長字段類型;OID 必須爲 long, int 或 short

native:依據底層數據庫對自動生成標識符的支持能力, 來選擇使用 identity, sequence 或 hilo 標識符生成器
適合於跨數據庫平臺開發;
OID 必須爲 long, int 或 short

複合主鍵
1.<composite-id>
   <key-property name="" column="" type=""/>
   <key-property name="" column="" type=""/>
  </composite-id>
2.將複合主鍵單獨創建一個類,在持久化類中用一個屬性表示
<composite-id name="" class="">

uuid:Hibernate會產生不重複的32位字符串作爲主鍵

關聯關係
<many-to-one name="外鍵屬性名" class="外鍵屬性對應類路徑" cascade="save-update">
 <column name="表中外鍵名"></column>
</many-to-one>
自動持久化所關聯對象
cascade="save-update",表示級聯保存和更新,當保存或更新對象時,此時會級聯保存或更新和此對象相關聯的其他對象,也就是將對象持久化

<set name="持久化類中集合的屬性名稱" table="集合屬性映射的多的一端外鍵表名稱" cascade="save-update">
 <key>
  <column name="外鍵列的名稱"></column>
 </key>
 <one-to-many class="一對多集合中對應的類型全路徑"/>
</set>
Hibernate要求在持久化類中定義集合屬性時,必須把屬性聲明爲接口類型;創建集合0表示初始集合的同時初始化集合的長度,避免空指針異常

對象導航:在兩端都配置cascade="save-update",保存一個對象,與之相關聯的對象也會保存

inverse:在hibernate中通過對inverse屬性的值決定是由雙向關聯的哪一方來維護表和表之間的關係.inverse=false 的爲主動,inverse=true 的爲被動方, 由主動方負責維護關聯關係。在沒有設置 inverse=true 的情況下,父子兩邊都維護父子關係。
在 1-n 關係中,將 n 方設爲主控方將有助於性能改善。

建立兩個對象的關聯關係:
customer.getOrders().add(order);

order.setCustomer(customer);同時修改關聯兩端的相應屬性會使程序更加健壯,提高業務邏輯層的獨立性,使業務邏輯層的程序代碼
不受Hibernate實現類的影響。

解除兩個對象的關聯關係:
Customer.getOrders().remove(order);

Order.setCustomer(null);

級聯刪除:cascade="delete"  當刪除對象的同時,級聯刪除和對象表相關的外鍵表中的數據。

自動刪除解除了關聯關係的對象(刪除孤兒):cascade="delete-orphan" 或 cascade="all-delete-orphan"(包含所有行爲)

在數據庫中對集合排序:<set order-by="id desc/asc">

操縱持久化對象
session.flush();清理session的一級緩存,讓緩存中的數據與數據庫同步,從而進行CRUD操作,方向:緩存--->數據庫,緩存中的數據不丟失
tx.commit():先調用session.flush()清理session的一級緩存,讓緩存中的數據與數據庫同步,然後再提交事務

session.clear();清空緩存,將一級緩存中的數據清空
session.refresh();重新刷新緩存區域,使緩存中的數據與數據庫同步,方向:數據庫--->緩存,使用對象的OID再查詢一遍數據庫

緩存清理模式:
session.setFlushMode(FlushMode.NEVER);//永不清理緩存
s.flush();此時可以清理session緩存
commit();此時不調用flush()

hibernate中java對象的狀態:

持久化狀態(託管):OID 不爲 null
;位於 Session 緩存中
;持久化對象和數據庫中的相關記錄對應;如果從臨時對象轉變而來,此時在數據庫中不存在對應記錄;Session 在清理緩存時, 會根據持久化對象的屬性變化, 來同步更新數據庫;
在同一個 Session 實例的緩存中, 數據庫表中的每條記錄只對應唯一的持久化對象

臨時狀態:OID 通常爲 null
;不處於 Session 的緩存中
;在數據庫中沒有對應的記錄

遊離狀態(脫管):OID 不爲 null
;不再處於 Session 的緩存中;
一般情況需下, 遊離對象是由持久化對象轉變過來的, 因此在數據庫中可能還存在與它對應的記錄。

刪除狀態:OID 不爲 null
;從一個 Session實例的緩存中刪除
;Session 已經計劃將其從數據庫刪除, Session 在清理緩存時, 會執行 SQL delete 語句, 刪除數據庫中的對應記錄。

evict():持久化狀態--->遊離狀態
update():遊離狀態--->持久化狀態

unsave-value:用來判斷當前對象是臨時對象還是持久對象,默認值是0

get()  load()
1.相同點:都可以根據給定的OID從數據庫中加載一個持久化對象
2.不同點:當數據庫中不存在與 OID 對應的記錄時, load() 方法拋出 ObjectNotFoundException 異常, 而 get() 方法返回 null

2013.7.12
組件:一個類(Address)不能單獨映射一個表,它的存在依賴於另一個主體類(Customer)
Customer.hbm.xml
<component name="持久化對象類中的屬性" class="該屬性的對應數據類型(全路徑)">
 <parent name="customer"/>//表示是屬於整體類的一部分(可加可不加)
 <property name="組件中的屬性名" column="映射數據表的列" type="hibernate的數據類型"/>
</component>

持久化類的屬性分爲兩種:
值(value)類型: 沒有 OID, 不能被單獨持久化, 生命週期依賴於所屬的持久化類的對象的生命週期,組件類型就是一種值類型
實體(entity)類型: 有 OID, 可以被單獨持久化, 有獨立的生命週期

映射多對多的關聯關係:使用set集合
中間表:將多對多的關係分成兩個一對多的關係
多對多的關聯關係修改中間表的時候,不是執行update,而是先刪除再插入

若管理關聯關係的一方(主控方)刪除該表數據時,先刪除中間表與另一表相關聯的數據,然後再刪除該表數據

hibernate的檢索策略:

立即檢索:立即加載檢索方法指定的對象,lazy="false"。
*會使用OID立即查詢數據庫,獲取該對象所有的的屬性。
延遲檢索:延遲加載檢索方法指定的對象,lazy="true"。
*當使用load方法通過OID進行查詢的時候,會生成一個代理對象,代理對象只初始化OID,查其他屬性時才查詢數據庫,顯示sql語句,獲取相應的其他屬性的值。
迫切左外連接檢索(fetch屬性值設爲“join”):通過左外連接加載與檢索指定的對象關聯的對象。
<class lazy="true">//說明當前類默認是延遲檢索
get方法使用OID進行查詢時,永遠是立即檢索
只有使用load方法才能夠測試出立即檢索和延遲檢索

判斷當前對象是延遲檢索還是立即檢索,判斷當前對象是否對值進行初始化: Hibernate.isInitialized(c)
對其進行初始化:
方法一:只要調用除OID之外的其他屬性,此時可以對代理對象進行初始化.
方法二:將代理對象進行初始化,查詢數據庫,對數據進行初始化: Hibernate.initialize(c);

類級別的檢索:session的方法直接檢索Customer對象,對Customer對象到底採用立即檢索
還是延遲檢索方式
通過class元素的lazy屬性設定。
關聯級別的檢索:通過set元素lazy屬性設定。

關聯級別set中
* lazy = true(默認值):延遲檢索,延遲加載只要調用關聯的訂單對象時才查詢數據庫
* lazy = false:立即檢索,只要初始化客戶對象,和它關聯的集合對象也馬上被初始化(馬上查詢數據庫)

一對多和多對多關聯的檢索策略(set): <set> 元素的 lazy 和 fetch 屬性:
fetch        lazy
-------------------------------------
join      false 採用迫切左外聯接檢索。
join      true 採用迫切左外聯接檢索。
join      extra 採用迫切左外聯接檢索。
select      false 採用立即檢索
select      true 採用延遲檢索
select      extra 採用延遲檢索(極其懶惰:只查需要的)
subselect    false 採用立即檢索(嵌套子查詢)
subselect    true 採用延遲檢索(嵌套子查詢)
subselect    extra 採用延遲檢索(極其懶惰)(嵌套子查詢)

迫切左外連接檢索(fetch 屬性值設爲 “join”)
Query 的list() 方法會忽略映射文件中配置的迫切左外連接檢索策略,而依舊採用立即檢索還是延遲加載策略由set集合的lazy屬性決定。

組合1 many2one立即檢索+set立即檢索
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="select" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="select" lazy="false">

組合2 many2one迫切左外+set立即檢索
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="join" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="select" lazy="false">

組合3 many2one立即檢索+set迫切左外
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="select" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="join" lazy="false">

批量檢索  從一的一端查詢  查詢所有的客戶:<set> 元素有一個batch-size 屬性,用來爲延遲檢索策略或立即檢索策略設定批量檢索的數量. 批量檢索能減少 SELECT 語句的數目, 提高延遲檢索或立即檢索的運行性能.  默認值是1。
注:query.list()屬於hql檢索,hql檢索忽略關聯級別的迫切左外連接檢索,只與lazy屬性有關.
當在<set>元素中定義batch-size=3(使用嵌套子查詢合併sql語句)

批量檢索  從多的一端查詢  查詢所有的訂單:在Customer.hbm.xml文件中增加batch-size屬性
當在Customer.hbm.xml的<class>元素中定義batch-size=3(使用嵌套子查詢合併sql語句)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章