Hibernate學習筆記二


一、持久化類的編寫規則

1、持久化類的概述

  持久化:將內存中的一個對象持久化到數據庫中的過程.Hibernate 框架就是用來持久化的框架
  持久化類:一個 Java 類與數據庫中的表建立映射關系.那么這個類在 Hibernate 中稱為持久化類
  持久化類 = Java 類 + 映射文件

2、持久化類的編寫規則

  • 對持久化類提供一個無參構造方法 :Hibernate 底層需要使用反射生成實例
  • 屬性需要私有,私有的屬性提供 get 和 set 方法 :Hibernate 中獲取、設置對象的值
  • 對持久化類提供一個唯一標識 OID 與數據庫主鍵對應 :Java 中通過內存地址區分是否是同一個
  • 對象,數據庫中通過主鍵區分是否為同一條記錄,Hibernate 中通過 OID 區分是否為同一個對象
  • 持久化類中屬性盡量使用包裝類 :因為基本數據類型默認值是:0,0有很多歧義.包裝類默認值為 null
  • 持久化類不要使用 final 修飾 :延遲加載本身是 Hibernate 的一個優化手段,返回一個代理對象(javassist可以對沒有實現接口的類產生代理--使用類非常底層的字節碼增強技術,繼承這個類進行代理)。如果不能被繼承,就不能產生代理對象,延遲加載也就失效了。load和 get 方法一致。

二、主鍵生成策略

1、主鍵的分類

  • 自然主鍵
    自然主鍵:主鍵本身就是表中的一個字段(實體類中的一個屬性)。創建一個人員表,使用身份證(唯一不可重復)作為主鍵,這種主鍵稱為自然主鍵

  • 代理主鍵
    代理主鍵:主鍵本身不是表中必須的一個字段(不是實體中的具體的屬性)。創建一個人員表,不使用身份證作為主鍵,使用不相關的ID作為主鍵,這種主鍵稱為代理主鍵。實際開發中,盡量使用代理主鍵

2、主鍵的生成策略

  Hibernate 的主鍵生成策略,在實際開發中一般不允許用戶手動設置主鍵,一般將主鍵交給數據庫,或者手動編寫程序進行設
置。在 Hibernate 中為了減少代碼編寫,提供了很多種主鍵生成的策略。

  • increment
    Hibernate 中提供的自動增長機制,適用 short int lang 類型的主鍵,在單線程程序中使用首先發送一條SQL語句:select max(id) from 表; 然后讓 id+1,作為下一條記錄的主鍵

  • identity
    適用 short int lang 類型的主鍵,使用的是數據庫底層的自動增長機制.適用於有自動增長機制的數據庫(MySQL), Oracle 沒有自動增長機制.

  • sequence
    適用於 short int lang 類型的主鍵,采用序列的方式.(Oracle支持序列),MySQL 不支持序列.

  • uuid
    適用於字符串類型的主鍵,使用 Hibernate 中隨機的方式生成字符串主鍵

  • native
    本地策略,可以在 identity 和 sequence 之間切換.

  • assigned
    Hibernate 放棄外鍵的管理,需要通過手動編寫程序和用戶自己設置.

  • foreign
    外部的,在一對一的關聯映射情況下使用.

三、持久化類的三種狀態

  Hibernate 是持久層的 ORM 框架,專注於數據的持久化工作。在進行數據持久化操作時,持久化對象可能處於不同的狀態當中。這些狀態可分為三種,分別為瞬時態、持久態和脫管態。下面分別針對這三種狀態進行簡單介紹。

1、三種狀態的介紹

  • 瞬時態(transient)
    瞬時態也稱為臨時態或者自由態,瞬時態的對象是由 new 關鍵字開辟內存空間的對象,不存在持久化標識 OID(相當於主鍵值),且未與任何的 Session 實例相關聯,在數據庫中也沒有記錄,失去引用后將被 JVM 回收。瞬時對象在內存孤立存在,它是攜帶信息的載體,不和數據庫的數據有任何關聯關系。

  • 持久態(persistent)
    持久態的對象存在一個持久化標識 OID,當對象加入到 Session 緩存中時,就與 Session 實例相關聯。它在數據庫中存在與之對應的記錄,每條記錄只對應唯一的持久化對象。需要注意的是,持久態對象是在事務還未提交前變成持久態的。

  • 脫管態(detached)
    脫管態也稱離線態或者游離態,當持久化對象與 Session 斷開時就變成了脫管態,但是脫管態依然存在持久化標識 OID,只是失去了與當前 Session 的關聯。需要注意的是,脫管態對象發生改變時Hibernate 是不能檢測到的。

2、三種狀態的區分

package com.qidishixun.Hibernate;

import com.qidishixun.Hibernate.domain.Customer;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import java.io.Serializable;

public class HibernateDemo2 {


    @Test
    public void test1(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = new Customer();
        //瞬時態對象:沒有唯一標識OID,被session 管理
        customer.setCust_name("張三豐");

        Serializable id = session.save(customer);

        //持久態對象:有唯一表示OID,被session 管理
        Customer customer2 = session.get(Customer.class,id);

        transaction.commit();
        session.close();

        //托管態對象:有唯一表示OID, 沒有被session管理,session已經close了
        System.out.println("客戶名稱:" + customer.getCust_name());

    }

}

3、三種狀態轉換

  • 三種狀態轉換圖

  • 瞬時態對象
獲得
Customer customer = new Customer();

狀態轉換
瞬時 --> 持久
save(Object obj)、saveOrUpdate(Object obj)

瞬時 --> 托管
customer.setCust_id(1L);

  • 持久態對象
獲得
get()、load()

狀態轉換
持久 --> 瞬時
delete();

持久 --> 托管
close()、clear()、evict()
  • 托管態對象
獲得
Customer customer = new Customer();
customer.setCust_id(1L);

狀態轉換
托管 --> 持久
update()、saveOrUpdate();

托管 --> 瞬時
customer.setCust_id(null);

4、持久態對象的特性

  • 持久態對象可以自動更新數據庫
    @Test
    public void test2(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //獲得持久態對象 get load
        Customer customer = session.get(Customer.class, 1L);
        customer.setCust_name("王娜");
//        session.update(customer);
        
        transaction.commit();
        session.close();
    }

四、Hibernate 的一級緩存

1、Hibernate 的一級緩存

  Hibernate 的一級緩存就是指 Session 緩存,Session 緩存是一塊內存空間,用來存放相互管理的Java 對象,在使用 Hibernate 查詢對象的時候,首先會使用對象屬性的 OID 值在 Hibernate 的一級緩存中進行查找,如果找到匹配的 OID 值的對象,就直接將該對象從一級緩存中取出使用,不會再查詢數據庫,如果沒有找到相同 OID 值的對象,則會去數據庫中查找響應數據。當從數據庫中查詢到所需數據時,該數據信息也會放置到一級緩存中。Hibernate 的一級緩存的作用就是減少對數據庫訪問的次數。
  在 Session 接口的實現中包含一系列的 Java 集合,這些 Java 集合構成了 Session 緩存。只要Session 實例沒有結束生命周期,存放在它緩存中的對象也不會結束生命周期。固一級緩存也被稱為Session 級別的緩存。
  Hibernate 的一級緩存有如下特點:當應用程序調用 Session 接口的 sava()、update、saveOrUpdate

2、證明 Hibernate 的一級緩存存在

package com.qidishixun.Hibernate;

import com.qidishixun.Hibernate.domain.Customer;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

/**
 * Hibernate 的一級緩存
 * @ClassName: HibernateDemo3
 * @Author Gui
 * @Date 2021/6/28
 * @Version 1.0
 */
public class HibernateDemo3 {


    @Test
    public void test1(){

        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        Customer customer1 = session.get(Customer.class, 1L);
        System.out.println(customer1);

        Customer customer2 = session.get(Customer.class, 1L);
        System.out.println(customer2);

        System.out.println(customer1 == customer2);

        transaction.commit();
        session.close();


    }
}

五、Hibernate 事務管理

1、綁定線程的 Session

  Hibernate5 中自身提供了三種管理 Session 對象的方法

  • Session 對象的生命周期與本地線程綁定
  • Session 對象的生命周期與 JTA 事務綁定
  • Hibernate 委托程序管理 Session 對象的聲明周期

  在 Hibernate 配置文件中,hibernate.current_session_context_class 屬性用於指定 Session 管理方式,可選值包括

  • thread: Session 對象的生命周期與本地線程綁定
  • jta: Session 對象的生命周期與 JTA 事務綁定
  • managed: Hibernate 委托程序管理 Session 對象的聲明周期

  在 hibernate.cfg.xml 配置文件中進行如下配置:

<!-- 配置 Session 綁定本地線程 -->
<property name="hibernate.current_session_context_class">thread</property>

2、修改 HibernateUtils 工具類

    /**
     * 提供獲得 Session方法
     * @return
     */
    public static Session getCurrentSession(){
        return sessionFaction.getCurrentSession();
    }

測試

    @Test
    public void test3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCust_name("大哥哥");
        session.save(customer);

        transaction.commit();
        //這里不需要關閉session,因為線程結束Session自動銷毀
    }

六、Hibernate 的其他 API

1、Query

  Query 代表面向對象的一個 Hibernate 操作. 在 Hibernate 中通常使用 session.createQuery() 方法接收一個 HQL 語句,然后使用 query 的 list() 或 uniqueResult() 方法執行查詢. 所謂的 HQL 是Hibernate Query Language 的縮寫,其語法很像 SQL 但是它是完全面向對象的.在 Hibernate 中使用 Query 的步驟:

  1. 獲得 Hibernate 的 Session 對象
  2. 編寫 HQL 語句
  3. 調用 session.createQuery() 創建查詢對象
  4. 如果 HQL 語句包含參數,則調用 Query 的 setXXX 方法設置參數
  5. 調用 Query 的 list() 或 uniqueResult() 方法執行查詢

  • 查詢所有
package com.qidishixun.Hibernate;

import com.qidishixun.Hibernate.domain.Customer;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import java.util.List;

/**
 * 利用Hibernate API 查詢數據庫表
 * @ClassName: HibernateDemo4
 * @Author Gui
 * @Date 2021/6/28
 * @Version 1.0
 */
public class HibernateDemo4 {

    @Test
    public void test1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from Customer";
        Query query = session.createQuery(hql);
        List<com.qidishixun.Hibernate.domain.Customer> customers = query.list();
        for (com.qidishixun.Hibernate.domain.Customer customer :customers){
            System.out.println(customer);
        }
        transaction.commit();
    }

}

  • 條件查詢
    /**
     * 模糊查詢
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from Customer where cust_name like ?";
        Query query = session.createQuery(hql);
        query.setParameter(0, "大%");
        List<com.qidishixun.Hibernate.domain.Customer> customers = query.list();
        for (com.qidishixun.Hibernate.domain.Customer customer : customers){
            System.out.println(customer);
        }
        transaction.commit();
    }
  • 分頁查詢
    /**
     * 分頁查詢
     */
    @Test
    public void test3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        String hql = "from Customer";
        Query query = session.createQuery(hql);

        //設置分頁查詢的條件
        query.setFirstResult(3); //從幾開始
        query.setMaxResults(3); //每頁顯示幾條

        List<com.qidishixun.Hibernate.domain.Customer> customers = query.list();
        for (Customer customer : customers){
            System.out.println(customer);
        }
        transaction.commit();
    }

2、Criteria

  Criteria:QBC查詢(Query By Criteria) ,更加面向對象的一種查詢方式

  • 查詢所有
package com.qidishixun.Hibernate;

import com.qidishixun.Hibernate.domain.Customer;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import java.util.List;

/**
 * 更加面向對象的一種查詢
 * @ClassName: HibernateDemo5
 * @Author Gui
 * @Date 2021/6/28
 * @Version 1.0
 */
public class HibernateDemo5 {

    @Test
    public void test1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        //通過 Session 獲取 criteria
        Criteria criteria = session.createCriteria(com.qidishixun.Hibernate.domain.Customer.class);
        List<com.qidishixun.Hibernate.domain.Customer> customers = criteria.list();
        for (com.qidishixun.Hibernate.domain.Customer customer : customers){
            System.out.println(customer);
        }

        transaction.commit();
    }
}

  • 條件查詢
    @Test
    public void test2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        //通過Session 獲取 criteria
        Criteria criteria = session.createCriteria(com.qidishixun.Hibernate.domain.Customer.class);

        //設置條件
        criteria.add(Restrictions.ilike("cust_name","小%"));

        List<com.qidishixun.Hibernate.domain.Customer> list = criteria.list();
        for (com.qidishixun.Hibernate.domain.Customer customer : list){
            System.out.println(customer);
        }

        transaction.commit();
    }

  • 分頁查詢
    /**
     * 分頁查詢
     */
    @Test
    public void test3(){

        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        //通過 Session 獲取 criteria
        Criteria criteria = session.createCriteria(com.qidishixun.Hibernate.domain.Customer.class);

        //設置分頁
        criteria.setFirstResult(1); //跳過幾個開始查詢
        criteria.setMaxResults(3);

        List<com.qidishixun.Hibernate.domain.Customer> list = criteria.list();
        for (Customer customer : list){
            System.out.println(customer);
        }
        transaction.commit();
    }

3、SQLQuery


    /**
     * HQL  和  SQL 的寫法
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
        List<Object[]> list1 = sqlQuery.list();
        for (Object[] object : list1){
            System.out.println(object.toString());
        }

        transaction.commit();
        session.close();
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM