1. 程式人生 > >Hibernate快速筆記1

Hibernate快速筆記1

視訊:Hibernate
資料與文件:領取 提取碼:p3es

路線:

  1. Hibernate的概述,原理,簡單的API使用
  2. 一級快取和其他API
  3. 1vN和NvN的配置
  4. Hibernate的查詢方式和抓取策略
  5. CRM案例

引入:CRM系統【百度百科】

  1. 客戶關係管理系統(CRM)是以客戶資料的管理為核心,利用資訊科學技術,實現市場營銷、銷售、服務等活動自動化,並建立一個客戶資訊的收集、管理、分析、利用的系統,幫助企業實現以客戶為中心的管理模式。客戶關係管理既是一種管理理念,又是一種軟體技術。

    客戶關係管理系統主要有高可控性的資料庫、更高的安全性、資料實時更新等特點,提供日程管理、訂單管理、發票管理、知識庫管理等功能。

  2. 客戶關係一對一理論。滿足每個客戶的特殊需求,同每個客戶建立聯絡,通過同客戶的聯絡來了解客戶的不同需求,並在此基礎上進行"一對一"個性化服務。

  3. 從新客戶接入到老客戶維護和營銷的每一個環節。與銷售、營銷、推廣、策劃、人事等多部門業務對接。優化各業務環節,減少各環節客戶流失,和公司成本。----------市場營銷、資料分析、掌控能力等

CRM系統是一種綜合性的概念,這樣的系統一般就是面向客戶的資料資訊,可以分為若干模組。如客戶資訊管理、聯絡人管理、統計分析、綜合查詢等。

簡單解釋,銷售方業務員工(使用者)使用這種系統,先去找到客戶方的某些代表的聯絡人(聯絡人管理),通過他們開發成客戶,並記錄這個過程中的資訊(客戶拜訪管理),然後把客戶的資料錄入系統(客戶資訊管理),然後可以隨時通過系統查詢上述這些所有的資訊(綜合查詢),進而進行一些相應的分析處理(統計分析)。 另外,這個系統本身還有一些基本的管理和使用,比如賬戶、日誌等(系統管理)。

本案例僅涉及CRM中客戶資訊管理的CRUD操作及配置


 

Hibernate是什麼?怎麼用?

框架是一種軟體的半成品,未完全加工。

經典的JAVA EE(服務端)分為Web、業務、持久三層結構。不同的技術和框架對應著不同的層次,這是在長期經驗下的產物,或者說建議。使用傳統的 Servlet + Jsp + JavaBean + JDBC 可以完成開發,但是框架的好處是加快快發效率,效能更加優越。

常用架構對應的分層示意圖:![圖一 EE的三層結構](assets/圖一 EE的三層結構2.bmp)

總結:持久層中的ORM框架,對JDBC進行了輕量級封裝,自動化。ORM也就是物件關係對映,將Java中的物件和資料庫的表通過xml做對映,達到操作物件就是直接操作表

的目的。

優點:1)對JDBC的輕量級封裝,簡化資料訪問層的重複性程式碼,減少記憶體消耗,提高效率
2)框架,優秀的ORM實現,簡化DAO(Data Access Object)層的實現
3)效能強,擴充套件性強——多種RDB,多種ER關係對映;可拓展,多種API,開源。【注】:效能高是相對的,一般來說越底層的訪問速率是越快的,而上層的提供了許多方便的拓展使用方法,進行了一些優化,達到提升效能的結果。
 

版本:3.x(5.x類似,相容),4.x
使用
  • [下載](<https://sourceforge.net/projects/hibernate/files/hibernate-orm/5.0.7.Final/)檔案,解壓;
  • 解壓檔案目錄中包含doc(文件),lib(庫),project(預設專案);其中lib中含有必須和非必須的各種庫檔案(jar包)
  • 建立Java專案或者WEB專案時均可引用,使用的方式就是導JAR包;
    • 資料庫操作的JAR包:資料庫驅動如 MySQL,JDBC/C3P0等
    • lib中的required中的包
    • 日誌記錄包log4j——便於開發

 

方式

  1. 建立資料表

  2. 建立實體類

  3. 使用hbm.xml(命名隨意,但約定字尾),配置對映關係

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<!-- 建立類與表的對映 -->
    	<class name="com.itheima.hibernate.demo1.Customer" table="cst_customer">
    		<!-- 建立類中的屬性與表中的主鍵對應 -->
    		<id name="cust_id" column="cust_id" >
    			<generator class="native"/>
    		</id>
    		
    		<!-- 建立類中的普通的屬性和表的欄位的對應 -->
    		<property name="cust_name" column="cust_name" length="32" />
    		<property name="cust_source" column="cust_source" length="32"/>
    		<property name="cust_industry" column="cust_industry"/>
    		<property name="cust_level" column="cust_level"/>
    		<property name="cust_phone" column="cust_phone"/>
    		<property name="cust_mobile" column="cust_mobile"/>
    	</class>
    </hibernate-mapping>
    
  4. Hibernate的全域性配置cfg.xml,配置的說明在解壓檔案下l\project\etc\hibernate.properties中有示例

    • 配置資料庫:驅動,伺服器,埠號,資料庫
    • Hibernate方言
    • 資料庫連線池
    • 匯入對映檔案

 

配置檔案

  1. 對映配置檔案 ------xxx.hbm.xml
    • <hibernate-mapping>下配置所有

    • <class>/<id>/<property>標籤

    • 欄位:name,column等,length在hibernate自動建表時使用

    • 【class標籤的配置】

      • 標籤用來建立類與表的對映關係

      • 屬性:

        • name :類的全路徑

        • table :表名(類名與表名一致,table可以省略

        • catalog :資料庫名

      【id標籤的配置】

      • 標籤用來建立類中的屬性與表中的主鍵的對應關係

      • 屬性:

        • name :類中的屬性名

        • column :表中的欄位名(類中的屬性名和表中的欄位名如果一致,column可以省略

        • length :長度

        • type :型別

      【property標籤的配置】

      • 標籤用來建立類中的普通屬性與表的欄位的對應關係

      • 屬性:

        • name :類中的屬性名

        • column:表中的欄位名

        • length :長度

        • type :型別

        • not-null :設定非空

        • unique :設定唯一

  2. hibernate核心配置 hibernate.cfg.xml
    • <hibernate-configuration>下配置所有,注:配置同樣可以使用properties檔案配置,但是這樣載入不了對映檔案
    • <session-factory>配置會話工廠,相當於配置不同的連線容器,用來解析後建立不同的連線池,包含多個連線,也就是session
    • 資料庫的配置(驅動,DB,賬戶,密碼等) 【必須】
    • 方言配置——控制不同的資料庫會話 【必須】
    • 對映檔案<mapping> , 也可以使用手動載入
    • 【可選】SQL語句的列印(console)與格式化,自動建立表——用作測試和驗證
      • 顯示SQL :hibernate.show_sql
        格式化SQL :hibernate.format_sql
        自動建表 :hibernate.hbm2ddl.auto
        • none:不使用hibernate的自動建表
        • create:如果資料庫中已經有表,刪除原有表,重新建立,如果沒有表,新建表。(測試)
        • create-drop :如果資料庫中已經有表,刪除原有表,執行操作,刪除這個表。如果沒有表,新建一個,使用完了刪除該表。(測試)
      • update:如果資料庫中有表,使用原有表,如果沒有表,建立新表(更新表結構)
      • validate :如果沒有表,不會建立表。只會使用資料庫中原有的表。(校驗對映和表結構)。

 

核心API (幾個物件)

  • Configuration: 載入核心配置檔案,對映配置檔案(手動載入);用來配置Hibernate,啟動Hibernate;啟動時對映到不同的xml檔案,然後建立SessionFactory物件。

  • SessionFactory:初始化hibernate,資料來源的代理(相當於連線池),session的工廠,使用Configuration建立;維護hibernate的資料庫連線池和二級快取(已基本棄用);執行緒安全的,一個專案只需一個;也可以手動配置另外的如C3P0連線池(需匯入相應的jar包)

    • 於是,可以在一個專案中,使用一個工具類,抽取出相應的Session工廠;
    • 同一個專案使用一個工廠即可,用來返回不同的session
  • Session:Session代表的是Hibernate與資料庫的連結物件,類似於connection。不是執行緒安全的,所有一般會獲取多個,單獨使用。與資料庫互動的橋樑。具有一批方法,來進行CRUD操作:

    • 儲存:Serializable save(Object obj); 返回序列化的鍵——序號

    • 查詢:T get(Class c,Serializable id); T load(Class c,Serializable id);

      get和load的區別:get是立即執行傳送SQL,返回查詢到的物件或者null;load懶載入,使用物件的時候才執行查詢的SQL(除了ID可以直接獲取外);

      get返回是真實物件,load返回的是代理物件(javassist),物件不存在的時候報錯

    • 修改:void update(Object obj);直接修改(相同ID的新物件替代),先查詢再修改

    • 刪除:void delete(Object obj);根據刪除(相同ID序號的新物件),先查詢再刪除,支援Hibernate的級聯刪除

    • 【不常用】儲存或更新:void saveOrUpdate(Object obj)

    • 【不常用】查詢所有: Query createSQLQuery(String sql) 同樣支援HQL createQuery()

  • Transaction:事務物件,commit、rollback


 

基礎筆記(案例一、基於Hibernate的DAO操作)

  1. 持久化與持久化類

    Hibernate是持久層的ORM對映框架,專注於資料的持久化工作——也就是記憶體資料永久性地寫入到資料庫中。Java中與資料庫表中完成對應的對映類檔案,稱為持久化類——或者說帶有對映檔案的Java類物件。

    • 持久化類的規則
      1. 必須有一個無參的建構函式:Hibernate使用反射來生成例項物件,類的class位元組碼需要;
      2. 私有屬性必須有get/set方法,Hibernate設定物件的值
      3. 類中必須一個和表主鍵對應的屬性——唯一性
      4. 類中屬性儘量使用包裝型別,如Integer,Long——基本資料型別的預設值是0,存在歧義,例如int型的年齡,入DB的是0,是0還是忘了插入?
      5. 類不用final進行修飾——與延遲載入有關,延遲載入是Hibernate的一種優化,返回的是代理物件,其底層用到了繼承,這樣一來會使延遲載入失效,而返回真實物件
  2. Hibernate主鍵生成策略
    • 自然主鍵:表本身中的一個欄位,具有實際意義,如身份證號,手機號
    • 代理主鍵:表本身不是必須的,與個體的屬性沒有太大關聯,如序列號,Cid,Sid等;【推薦使用
    • 原則:開閉原則,對拓展是開放的,對修改時封閉的
    • 生成策略:Hibernate提供多種主鍵的生成策略,不需要使用者自己操作
      • increment:Hibernate的自增長,適用於short、int、long等型別主鍵,單執行緒使用;select max(ID) from 表,然後加1作為下一條記錄,存線上程安全問題
      • identity:資料庫底層的自增長,不會產生執行緒安全問題,適用於short/int/long等,適用於有自增長的資料庫產品,oracle不行
      • sequence:適用於short、int、long等型別主鍵,適用含有序列的資料庫,MySQL不支援
      • uuid:字串型別主鍵,Hibernate隨機生成
      • native:本地策略,可以視作在identity和sequence自動切換
      • assigned:Hibernate不設定主鍵,需要手動插入
      • foreign:外部,一對一的一種關聯情況下使用
  3. 持久化類的三種狀態
    • 瞬時態:沒有唯一的標識OID,沒有被session管理
    • 持久態:有唯一標識OID,被session管理
    • 脫管態:有唯一標識OID,不被session管理;new 物件後,設定ID即可;將ID置為null,則轉為瞬時態;

    在這裡插入圖片描述

    • 持久化類:**可以自動更新資料庫;**Hibernate的一級快取,也就是資料庫資料的備份,儲存在記憶體中
      • 一級快取,和session控制,生命週期與session一致;Hibernate預設自帶與開啟;用於減少對資料庫的訪問;呼叫session集合中的方法時,先訪問快取,沒有則訪問資料庫,然後將其載入到一級快取中。呼叫close()時,關閉session的快取內容,clear()情況所有快取,evict(object)清楚單個物件
      • 二級快取,需要手動開啟,暫時不常用;
      • 自動更新資料庫:通過Hibernate快取和快照實現,如果快取和快照區資料不同了,那麼就會將快取更新到資料庫中(事務提交時)。
  4. 事務

    事務ACID,由隔離性引發的問題——讀和寫。

    讀問題:髒讀、不可重複讀、幻(虛)讀

    寫問題:引發兩類丟失更新

    1. 事務隔離級別

      • read-un-commit: 未提交讀
      • read-commited:讀已提交 Oracle預設
      • repeatable read:重複讀 MySQL預設
      • Serializable:序列化
    2. Hibernate的隔離級別配置:核心配置檔案cfg.xml中,<property name="hibernate.connection.isolation">1/2/4/8</property>

    3. 在開發中,DAO層負責單個的執行邏輯,對業務而言,service層才是處理事務的邏輯;這需要在事務的處理過程中,多個DB操作使用的是同一個連線物件(connection/session)。兩種解決方法:1.向下傳遞同一個session物件;2. 使用ThreadLocal執行緒進行事務操作的繫結。

      Hibernate的事物執行緒繫結,需要配置<property name="hibernate.current_session_context_class">thread/jta等</property>;配置完後即可在service包含的多個DAO操作中,通過獲取當前執行緒中已繫結的session物件,完成;

      繫結執行緒後的session不需要再進行手動關閉,執行緒結束後自動關閉;

  5. 其他API
    1. query:查詢操作,接受HQL,查詢多個物件,返回唯一結果等

      示例:

      public void demo4() {
      		//Query		
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction transaction = session.beginTransaction();
      		//查詢所有
      		String hql = "from Customer";
      		Query query = session.createQuery(hql);
      		List<Customer> list = query.list();
      		
      //		for (Customer customer : list) {
      //			System.out.println(customer);
      //		}
      		//條件查詢
      //		String hql2 = "from Customer where cust_name like ?";
      //		Query query2 = session.createQuery(hql2);
      //		query2.setParameter(0, "1%");
      //		list = query2.list();
      //		for (Customer customer : list) {
      //			System.out.println(customer);
      //		}
      		
      		//分頁查詢
      		String hql3 = "from Customer";
      		Query query3 = session.createQuery(hql3);
      		//起點
      		query3.setFirstResult(2);
      		//size
      		query3.setMaxResults(1);
      		list = query3.list();
      		for (Customer customer : list) {
      			System.out.println(customer);
      		}
      		
      		transaction.commit();
      	}
      
    2. Criteria:面向物件查詢,QBC查詢

      public void demo() {
      		Session session = HibernateUtils.getCurrentSession();
      		Transaction transaction = session.beginTransaction();
      		//查詢所有
      		Criteria criteria = session.createCriteria(Customer.class);
      		List<Customer> list = criteria.list();
      		//條件查詢
      		//criteria.add(Restrictions.like("cust_name", "1%"));
      		List<Customer> list2 = criteria.list();
      		//分頁
      		criteria.setFirstResult(0);
      		criteria.setMaxResults(2);
      		List<Customer> list3 = criteria.list();
      		for (Customer customer : list3) {
      			System.out.println(customer);
      		}
      		transaction.commit();		
      	}
      
    3. SQLQuery:SQL的查詢,一般不常用

 

一對多的關係

案例:CRM中的客戶和聯絡人

  • 配置:一端和多端的實體都要使用實體物件的引用進行關係的關聯;在各自的對映配置檔案中,也需要使用關聯的配置
  • 級聯操作:測試中,1的物件需要新增多的引用,多的集合要將1新增進來;沒有在配置檔案中配置級聯儲存或更新,則需要兩端同時儲存;否則儲存了主體物件即可,也不需要配置雙向的關聯關係。
  • 級聯刪除:刪除1,多方參考的外來鍵置為null(預設);設定了1的級聯刪除,則刪除時同時刪除關聯的多方;也可以設定多方的級聯,刪除時同時刪除關聯的1方資料,且和1方關聯的多方的其他資料也會刪除(基本不用)
  • cascade和inverse的區別:前者設定的是物件間的關聯關係,後者管理的是鍵的管理關係;預設一方的inverse為false,表示不放棄外來鍵的管理權。置為True後,儲存1方的物件,會儲存其關聯(cascade)的多方物件入庫,但是卻沒有外來鍵

 

多對多的關係

  • 多對多的關係,需要配置兩個實體外,還需要一個關聯表
  • 如果進行的是雙向關聯,二者必須有一個放棄外來鍵的控制,否則關聯表中將會出現主鍵重複的衝突;非雙向關聯則不會出現錯誤
  • 級聯儲存或更新:設定後可以只儲存主體一方,否則出現瞬時物件異常;設定級聯後不需要雙向關聯
  • 級聯刪除:【基本不用】沒有設定級聯刪除時,只會刪除本表和關聯表;設定cascade後,會將關聯的表中資料一併刪除

一對一的關係

 

  • 一般轉化為唯一外來鍵對應
  • 或直接主鍵對應