Hibernate基礎知識(二)

Hibernate_day02總結

今日內容

Hibernate持久化對象的狀態

Hibernate一級緩存

Hibernate操作持久化對象的方法

Hibernate 關聯關係映射

 

1.1 上次課內容回顧

Hibernate:

* 第一天環境搭建,開發流程,配置和API

* 第二天Hibernate持久化對象的狀態,一級緩存,關聯關係映射.

* 第三天Hibernate的檢索方式 抓取策略 二級緩存.

* 第四天Hibernate練習:

 

1.Hibernate框架的概述:

* 就是一個持久層的ORM框架.

* ORM:對象關係映射.Java中實體對象與關係型數據庫中表建立一種關係.Hibernate中可以通過操作對象的方式,從而操作數據庫的表.

* 常見的持久層框架:

* Hibernate

* MyBatis

* JPA

* DBUtils

* Hibernate3.xHibernate4.x

 

2.Hibernate快速入門:

2.1下載Hibernate開發包.

2.2Hibernate開發包目錄結構:

* 文檔:

* 開發包:

* 操作字節碼:

* 必須的

* 可選的

* jpa

* 項目:

2.3創建一個java項目 導入相應jar.

2.4創建數據庫表:

2.5創建一個實體類:

2.6建立映射:

2.7創建Hibernate核心配置文件:

2.8編寫一個測試類:

3.HibenrateCRUD的操作:

* save();

* update();

* delete();

* get()/load();

* 區別:

* get:採用是立即檢索,馬上發送SQL查詢.返回的是真實對象.檢索一個找不到的對象的時候NullPointException

* load:採用延遲加載技術,當真正使用這個對象的時候,纔會發送SQL.返回代理對象.檢索一個找不到的對象的時候ObjectNotFoundException

4.Hibernate的常見配置及API:

* 4.1核心配置:

* 兩種方式;

* 屬性文件的方式:

* src下創建一個hibernate.properties.

***** 手動加載映射文件.

* XML格式的配置:

* src下創建一個hibernate.cfg.xml

 

* 必須的配置:

* 數據庫連接信息.

* Hibernate的方言.

* 可選配置:

* 顯示SQL

* 格式化SQL

* hbm2ddl.auto

* create/create-drop/update/validate

* 映射文件:

* <mapping resource=””/>

* 4.2映射配置:

* <class>建立類與表映射

* name:類的全路徑

* table:表名稱

* <id>

* name

* column

* type

* length

* <property>

* name

* column

* type

* length

 

5.HibernateAPI

* Configuration:管理配置信息.

* 屬性文件:

* 直接創建.

* XML

* new Configuration().configure();

 

* SessionFactory:

* 維護二級緩存,線程安全的對象.

* 抽取工具類.

 

* Session:

* 維護一級緩存,線程不安全的對象.

 

* Transaction:

***** 事務是默認不自動提交,手動提交事務.

* Query:

* Criteria:

 

6.持久化類編寫:

* 持久化類:就是一個實體類 + XML映射.

* 編寫原則:

* 無參數構造:

* 屬性提供set/get方法

* 提供爲一個標識:

* 儘量使用包裝類型:

* 這個類儘量不要使用final修飾.

 

* 自然主鍵和代理主鍵:

* Hibernate提供主鍵生成策略:

* increment:

* identity:

* sequence:

* uuid:

* native:

* assgined:

 

1.2 Hibernate的持久化類狀態:

1.2.1 Hibernate的持久化類狀態

持久化類:就是一個實體類 與 數據庫表建立了映射.

* Hibernate爲了方便管理持久化類,將持久化類分成了三種狀態.

瞬時態 transient:(臨時態)

 

持久態 persistent:

 

脫管態 detached:(離線態)

 

1.2.2 三種持久化對象的狀態:

Transient瞬時態:

特點:持久化對象沒有唯一標識OID.沒有納入Session的管理.

 

Persistent持久態:

特點:持久化對象有唯一標識OID.已經納入到Session的管理.

 

***** 結論:持久化持久態對象有自動更新數據庫的能力.

Detached脫管態:

特點:持久化對象有唯一標識OID,沒有納入到Session管理.

 

1.2.3 區分三種持久化對象的狀態:

@Test

// 區分持久化對象的三種狀態:

public void demo1(){

// 1.創建Session

Session session = HibernateUtils.openSession();

// 2.開啓事務

Transaction tx = session.beginTransaction();

// 向數據庫中保存一本圖書:

Book book = new Book();// 瞬時態:沒有唯一標識OID,沒有與session關聯.

book.setName("Hiernate開發");

book.setAuthor("XX");

book.setPrice(65d);

session.save(book); // 持久態:有唯一標識OID,session關聯.

// 3.事務提交

tx.commit();

// 4.釋放資源

session.close();

book.setName("Struts2開發"); // 脫管態:有唯一的標識,沒有與session關聯.

}

 

1.2.4 三種狀態對象轉換:

瞬時態:

獲得:

Book book = new Book();

 

瞬時--->持久

* save(book);

* save()/saveOrUpdate();

瞬時--->脫管

* book.setId(1);

持久態:

獲得:

Book book = (Book)session.get(Book.class,1);

* get()/load()/find()/iterate();

 

持久--->瞬時:

* delete(book);

* 特殊狀態:刪除態.(被刪除的對象,不建議去使用.)

 

持久--->脫管:

* session.close();

* close()/clear()/evict();

脫管態:

獲得:

Book book = new Book();

book.setId(1);

 

脫管--->持久:

* session.update();

* update()/saveOrUpdate()/lock()

 

脫管--->瞬時:

* book.setId(null);

 

1.2.5 持久態對象有自動更新數據庫的能力;

@Test

// 測試持久態的對象自動更新數據庫

public void demo2(){

// 1.創建Session

Session session = HibernateUtils.openSession();

// 2.開啓事務

Transaction tx = session.beginTransaction();

// 獲得一個持久態的對象.

Book book = (Book) session.get(Book.class, 1);

book.setName("Struts2開發");

// session.update(book);

// 3.提交事務

tx.commit();

// 4.關閉資源

session.close();

}

 

****** 自動更新數據庫的能力依賴了Hibernate的一級緩存.

1.3 Hibernate的一級緩存:(重要)

1.3.1 Hibernate的一級緩存:

什麼是緩存:

* 緩存將數據庫/硬盤上文件中數據,放入到緩存中(就是內存中一塊空間).當再次使用的使用,可以直接從內存中獲取.

 

緩存的好處:

* 提升程序運行的效率.緩存技術是Hibernate的一個優化的手段.

 

Hibernate分成兩個基本的緩存:

* 一級緩存:Session級別的緩存.一級緩存與session的生命週期一致.自帶的.不可卸載.

* 二級緩存:SessionFactory級別的緩存.不是自帶的.

 

Session 接口的實現中包含一系列的 Java 集合, 這些 Java 集合構成了 Session 緩存. 只要 Session 實例沒有結束生命週期, 存放在它緩存中的對象也不會結束生命週期.

1.3.2 證明Hibernate的一級緩存的存在:

@Test

// 證明一級緩存的存在

public void demo3(){

// 1.創建Session

Session session = HibernateUtils.openSession();

// 2.開啓事務

Transaction tx = session.beginTransaction();

// save方法可以向一級緩存中存放數據的.

/*Book book = new Book();

book.setName("JQuery開發");

book.setAuthor("XX");

book.setPrice(45d);

Integer id = (Integer) session.save(book);

Book book2 = (Book) session.get(Book.class, id);

System.out.println(book2);*/

// 分別用get執行兩次查詢.

Book book1 = (Book) session.get(Book.class, 1);// 馬上發生SQL去查詢

System.out.println(book1);

Book book2 = (Book) session.get(Book.class, 1);// 不發生SQL,因爲使用一級緩存的數據

System.out.println(book2);

// 3.提交事務

tx.commit();

// 4.關閉資源

session.close();

}

 

1.3.3 深入理解一級緩存中快照區:

@Test

// 深入理解一級緩存結構:快照區:

public void demo4(){

// 1.創建Session

Session session = HibernateUtils.openSession();

// 2.開啓事務

Transaction tx = session.beginTransaction();

// 獲得一個持久態的對象.

Book book = (Book) session.get(Book.class, 1);

book.setName("Spring3開發");

// 3.提交事務

tx.commit();

// 4.關閉資源

session.close();

}

 

結論:向一級緩存存入數據的時候,放入一級緩存區和一級緩存快照區,當更新了一級緩存的數據的時候,事務一旦提交,比對一級緩存和快照區,如果數據一致,不更新,如果數據不一致,自動更新數據庫.

1.3.4 Hibernate管理一級緩存:

一級緩存是與session的生命週期相關的.session生命週期結束,一級緩存銷燬了.

* clear()/evict()/flush()/refresh()管理一級緩存.

* clear():清空一級緩存中所有的對象.

* evict(Object obj):清空一級緩存中某個對象.

* flush():刷出緩存.

* refresh(Object obj):將快照區的數據重新覆蓋了一級緩存的數據.

1.3.5 Hibernate一級緩存的刷出時機:(瞭解.)

FlushMode:

* 常量:

* ALWAYS:每次查詢的時候都會刷出.手動調用flush.事務提交的時候.

* AUTO:默認值.有些查詢會刷出.手動調用flush.事務提交的時候.

* COMMIT:在事務提交的時候,手動調用flush的時候.

* MANUAL:只有在手動調用flush纔會刷出.

 

嚴格程度:MANUAL > COMMIT > AUTO > ALWAYS

1.4 操作持久化對象的方法:

save():

保存一條記錄:將瞬時態對象轉成持久態對象.

update()

更新一條記錄:將脫管態對象轉成持久態對象.

<class>標籤上設置select-before-update="true"在更新之前先去查詢

saveOrUpdate():

根據對象狀態的不同執行不同的save獲得update方法.

* 如果對象是一個瞬時態對象:執行save操作.

* 如果對象是一個脫管態對象:執行update操作.

* 設置id不存在,就會報錯,可以在<id>上設置一個unsaved-value=-1,執行保存的操作.

delete():

將持久態對象轉成瞬時態.

get()/load():

獲得一個持久態對象.

1.5 Hibernate關聯關係的映射:

1.5.1 實體之間的關係:

實體之間有三種關係:

* 一對多:

* 一個用戶,生成多個訂單,每一個訂單隻能屬於一個用戶.

* 建表原則:

* 在多的一方創建一個字段,作爲外鍵,指向一的一方的主鍵.

* 多對多:

* 一個學生可以選擇多門課程,一個課程可以被多個學生選擇.

* 建表原則:

* 創建第三張表,中間表至少有兩個字段,分別作爲外鍵指向多對多雙方主鍵.

* 一對一:(特殊.最少.)

* 一個公司只能有一個註冊地址,一個註冊地址,只能被一個公司使用.(否則將兩個表建到一個表.)

* 建表原則:

* 唯一外鍵:

* 一對一的雙方,假設一方是多的關係.需要在多的一方創建一個字段,作爲外鍵.指向一的一方的主鍵.但是在外鍵添加一個unique.

* 主鍵對應:

* 一對一的雙方,通過主鍵進行關聯.

 

1.5.2 Hibernate中一對多的配置:(*****)

第一步:

* 創建兩個實體:

* 客戶實體:

public class Customer {

private Integer cid;

private String cname;

// 一個客戶有多個訂單.

private Set<Order> orders = new HashSet<Order>();

public Integer getCid() {

return cid;

}

public void setCid(Integer cid) {

this.cid = cid;

}

public String getCname() {

return cname;

}

public void setCname(String cname) {

this.cname = cname;

}

public Set<Order> getOrders() {

return orders;

}

public void setOrders(Set<Order> orders) {

this.orders = orders;

}

}

 

* 訂單實體:

public class Order {

private Integer oid;

private String addr;

// 訂單屬於某一個客戶.放置一個客戶的對象.

private Customer customer;

public Integer getOid() {

return oid;

}

public void setOid(Integer oid) {

this.oid = oid;

}

public String getAddr() {

return addr;

}

public void setAddr(String addr) {

this.addr = addr;

}

public Customer getCustomer() {

return customer;

}

public void setCustomer(Customer customer) {

this.customer = customer;

}

}

 

第二步:建立映射:

Customer.hbm.xml

<hibernate-mapping>

<class name="cn.itcast.hibernate3.demo2.Customer" table="customer">

<!-- 配置唯一標識 -->

<id name="cid" column="cid">

<generator class="native"/>

</id>

<!-- 配置普通屬性 -->

<property name="cname" column="cname" length="20"/>

<!-- 建立映射 -->

<!-- 配置一個集合 <set>name Customer對象中的關聯對象的屬性名稱. -->

<set name="orders">

<!-- <key>標籤中column:用來描述一對多多的一方的外鍵的名稱. -->

<key column="cno"></key>

<!-- 配置一個<one-to-many>標籤中class屬性:訂單的類的全路徑 -->

<one-to-many class="cn.itcast.hibernate3.demo2.Order"/>

</set>

</class>

</hibernate-mapping>

 

Order.hbm.xml

<hibernate-mapping>

<class name="cn.itcast.hibernate3.demo2.Order" table="orders">

<!-- 配置唯一標識  -->

<id name="oid" column="oid">

<generator class="native"/>

</id>

<!-- 配置普通屬性 -->

<property name="addr" column="addr" length="50"/>

<!-- 配置映射 -->

<!--

<many-to-one>標籤

name :關聯對象的屬性的名稱.

column:表中的外鍵名稱.

class:關聯對象類的全路徑

-->

<many-to-one name="customer" column="cno" class="cn.itcast.hibernate3.demo2.Customer"/>

</class>

</hibernate-mapping>

 

第三步:將映射放到核心配置文件中.

 

1.5.3 Hibernate中級聯保存的效果:

級聯:操作當前對象的時候,關聯的對象如何處理.

 

cascade=save-update

級聯方向性:

* 保存客戶的時候,選擇級聯訂單.

* 保存訂單的時候,選擇級聯客戶.

 

1.5.4 Hibernate中級聯刪除的效果:

cascade=delete

1.5.5 Hibernate中的級聯取值:

none:不使用級聯

dave-update:保存或更新的時候級聯

delete:刪除的時候級聯

all:除了孤兒刪除以外的所有級聯.

delete-orphan:孤兒刪除(孤子刪除).

* 僅限於一對多.只有一對多時候,纔有父子存在.認爲一的一方是父親,多的一方是子方.

* 當一個客戶與某個訂單解除了關係.將外鍵置爲null.訂單沒有了所屬客戶,相當於一個孩子沒有了父親.將這種記錄就刪除了.

all-delete-orphan:包含了孤兒刪除的所有的級聯.

1.5.6 雙向維護產生多餘的SQL:

配置inverse=true:在那一端配置.那麼那一端放棄了外鍵的維護權.

* 一般情況下,一的一方去放棄.

 

cascade:操作關聯對象.

inverse:控制外鍵的維護.

1.5.7 Hibernate的多對多的配置:

第一步:創建實體類:

學生的實體:

public class Student {

private Integer sid;

private String sname;

// 一個學生選擇多門課程:

private Set<Course> courses = new HashSet<Course>();

public Integer getSid() {

return sid;

}

public void setSid(Integer sid) {

this.sid = sid;

}

public String getSname() {

return sname;

}

public void setSname(String sname) {

this.sname = sname;

}

public Set<Course> getCourses() {

return courses;

}

public void setCourses(Set<Course> courses) {

this.courses = courses;

}

}

課程的實體:

public class Course {

private Integer cid;

private String cname;

// 一個課程被多個學生選擇:

private Set<Student> students = new HashSet<Student>();

public Integer getCid() {

return cid;

}

public void setCid(Integer cid) {

this.cid = cid;

}

public String getCname() {

return cname;

}

public void setCname(String cname) {

this.cname = cname;

}

public Set<Student> getStudents() {

return students;

}

public void setStudents(Set<Student> students) {

this.students = students;

}

}

 

第二步建立映射:

Student.hbm.xml

<hibernate-mapping>

<class name="cn.itcast.hibernate3.demo3.Student" table="student">

<!-- 配置唯一標識 -->

<id name="sid" column="sid">

<generator class="native"/>

</id>

<!-- 配置普通屬性 -->

<property name="sname" column="sname" length="20"/>

<!-- 配置關聯映射 -->

<!-- <set>標籤 name:對應學生中的課程集合的名稱   table:中間表名稱. -->

<set name="courses" table="stu_cour">

<!-- <key>column寫 當前類在中間表的外鍵.-->

<key column="sno"></key>

<!-- <many-to-many>class:另一方類的全路徑. column:另一方在中間表中外鍵名稱-->

<many-to-many class="cn.itcast.hibernate3.demo3.Course" column="cno"/>

</set>

</class>

</hibernate-mapping>

 

Course.hbm.xml

<hibernate-mapping>

<class name="cn.itcast.hibernate3.demo3.Course" table="course">

<!-- 配置唯一標識 -->

<id name="cid" column="cid">

<generator class="native"/>

</id>

<!-- 配置普通屬性 -->

<property name="cname" column="cname" length="20"/>

<!-- 配置與學生關聯映射 -->

<!-- <set>name:對應當前類中的學生的集合的名稱  table:中間表的名稱-->

<set name="students" table="stu_cour">

<!-- <key>column:當前類在中間表中外鍵 -->

<key column="cno"></key>

<!-- <many-to-many>class:另一方的類全路徑. column:另一方在中間表中外鍵名稱 -->

<many-to-many class="cn.itcast.hibernate3.demo3.Student" column="sno"/>

</set>

</class>

</hibernate-mapping>

 

第三步:將映射文件加入到核心配置文件中:

今天的內容總結:

Hibernate持久化對象的狀態:

* 瞬時態:

* 持久態:

* 脫管態:

 

* 狀態之間的轉換:

 

Hibernate一級緩存:

* Hibernate的一級緩存的存在.

* get/load/save

* Hibernate的一級緩存的結構:

* 快照區.

* Hibernate一級緩存的管理:

* clear()/evict()/flush()/refresh();

* 刷出時機(瞭解)

 

Hibernate操作持久化對象常用方法:

* save();

* update();

* saveOrUpdate();

* 瞬時:執行save

* 脫管:執行update

* delete();

* get()/load();直接獲得持久對象.

 

Hibernate的關聯關係:(*****)

* 一對多的配置:(手動配置)

* 級聯.

* 多對多的配置:(手動配置)

* 級聯:

 

 ***********************************************************************************************************************************************************************

Hibernate的一級緩存的快照區


實體之間的關係


Hibernate的雙向維護產生多餘的SQL語句


發佈了66 篇原創文章 · 獲贊 22 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章