1. 程式人生 > >Hibernate(四):Hibernate的初始化,增刪改查等方法

Hibernate(四):Hibernate的初始化,增刪改查等方法

1,Hibernate初始化類

package com.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;


public class HibernateInit {
    private static SessionFactory sessionFactory=null;
    //SessionFactory和Configuration對整個應用來說,只有一個例項存在
    //為使用者訪問定義了一個本地執行緒變數,是靜態的,對每一個訪問該執行緒的使用者產生一個例項
    private static final ThreadLocal<Session> threadlocal=new ThreadLocal<Session>();

    static
    {
        try{
            Configuration cfg=new Configuration().configure();
            sessionFactory=cfg.buildSessionFactory();

        }catch (Exception e)
        {
            System.out.println("建立會話工廠失敗");
            e.printStackTrace();
        }
    }

    //要取得Session物件時,首先從當前使用者的執行緒取得Session物件。
    //如果還沒有建立,從SessionFactory中建立一個Session
    //此時會判斷SessionFactory物件是否已經建立
    //過程:
    //首先判斷threadLocal中是否存在Session物件
    // 如果不存在 則建立Session物件
    // 在建立Session物件時 首先要判斷系統是否已經載入Configuration
    // 如果沒有sessionFactory 則需要先建立該物件
    // 建立完成的Session物件 需要儲存在threadLocal中以供本次訪問執行緒的下一次呼叫
    public static  Session getSession() throws HibernateException{
        Session session=(Session)threadlocal.get();
        if(session==null || !session.isOpen())
        {
            if(sessionFactory==null)
            {
                rebulidSessionFactory();
            }
            session=(sessionFactory!=null)?sessionFactory.openSession():null;
            threadlocal.set(session);
        }
        return session;
    }

    private static void rebulidSessionFactory() {
        try{
            Configuration cfg=new Configuration().configure();
            sessionFactory=cfg.buildSessionFactory();
        }catch (Exception e)
        {
            System.err.println("建立會話工廠失敗");
            e.printStackTrace();
        }
    }
    public static SessionFactory getSessionFactory()
    {
        return sessionFactory;
    }
  //  在關閉Session物件是 只需要從當前執行緒中取得Session物件 關閉該物件 並置空本地執行緒變數即可
    public static void closeSession() throws HibernateException{
        Session session=(Session)threadlocal.get();
        threadlocal.set(null);
        if(session!=null)
        {
            session.close();
        }
    }
}

2.儲存資料:

   1. Session的save()方法是一個臨時物件轉變成持久化物件

   2.完成以下操作:

  •  將new物件加入到Session快取器中,使它進入持久化狀態
  •   選用對映檔案指定識別符號生成器,為持久化物件分配唯一的OID,在使用代理主鍵的情況下,setId()方法為New物件設定的OID使用無效
  •   計劃執行一條insert語句:在flush快取的時候

   3. Hibernate 通過持久化物件的 OID 來維持它和資料庫相關記錄的對應關係. 當 News 物件處於持久化狀態時, 不允許程式隨意修改它的 ID

程式碼如下:

package com.Test;

import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;

public class AddProduct {
    /**
     * 新增商品
     */
    public static void main(String[] args) {
        Session session = null;			//宣告Session物件
        Product product = new Product();//例項化持久化類
        //為持久化類屬性賦值
        product.setName("Java Web程式設計寶典");//設定產品名稱
        product.setPrice(79.00);//設定產品價格
        product.setFactory("明日科技");//設定生產商
        product.setRemark("無");//無
        //Hibernate的持久化操作
        try {
            session = HibernateInitialize.getSession();//獲取Session
            session.beginTransaction();//開啟事務
            session.save(product);//執行資料庫新增操作
            session.getTransaction().commit();//事務提交
        } catch (Exception e) {
            session.getTransaction().rollback();//事務回滾
            System.out.println("資料新增失敗");
            e.printStackTrace();
        }finally{
            HibernateInitialize.closeSession();//關閉Session物件
        }
    }
}

執行完成後:


注意:持久化狀態product在建立後是瞬時狀態,在Session執行完save()後,持久化物件product狀態變為持久化狀態,但這時的資料庫操作並沒有交給資料庫,在事務執行commit()方法後,才完成資料庫的新增操作。此時的持久化物件product變為髒資料,Session關閉後,持久化物件product的狀態變為遊離狀態,最後被JVM回收

3.查詢資料:

    Session物件提供了兩種物件裝載的方法:get()和load

  (1)get()方法

  •  如果不缺定資料庫中是否有匹配的記錄存在,就可以使用get()方法進行物件裝載、
  •  它會立即訪問資料庫,如果資料庫中沒有匹配記錄在,會返回null(返回值可能是持久化物件,也可以是null)
  •   get()方法裡面有兩個引數:一個持久化物件,另一個是持久化物件中的唯一標識

程式碼如下:

package com.Test;

import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;

public class GetProduct {
    public static void main(String[] args)
    {
        Session session=null;
        try{
            session= HibernateInitialize.getSession();
            Product product=(Product)session.get(Product.class,new Integer(0));
            System.out.println("產品名稱:"+product.getName());
            System.out.println("產品價格:"+product.getPrice()+"元");
            System.out.println("生產廠商:"+product.getFactory());
            System.out.println("產品備註:"+product.getRemark());
        }catch (Exception e)
        {
            System.out.println("物件裝載失敗");
        }finally {
            HibernateInitialize.closeSession();
        }
    }
}

在控制檯輸出資料,截圖如下:

  

(2)load()方法

      返回物件的代理,只有在返回物件被呼叫時,Hibernate才會發出SQL語句去查詢物件

程式碼如下:

package com.Test;

import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;

public class LoadProduct {
    public static void main(String[] args) {

        Session session = null;
        try {
            //Hibernate的持久化操作
            session = HibernateInitialize.getSession();//獲取Session
            Product product = new Product();//例項化物件
            session.load(product, new Integer("0"));//裝載物件
            //Product product = (Product) session.load(Product.class, new Integer("1"));//裝載物件
            System.out.println("產品ID:" + product.getId());
            System.out.println("產品名稱:" + product.getName());
            System.out.println("產品價格:" + product.getPrice() + "元");
            System.out.println("生產廠商:" + product.getFactory());
            System.out.println("產品備註:" + product.getRemark());
        } catch (Exception e) {
            System.out.println("物件裝載失敗");
            e.printStackTrace();
        } finally {
            HibernateInitialize.closeSession();//關閉Session
        }
    }
}
在控制檯輸出資料,截圖如下:


(3)區別:

   相同:都可以根據給定的OID從資料庫中載入一個持久化類物件

   不同點:

  • get方法會在呼叫之後立即向資料庫發出sql語句(不考慮快取的情況下),返回持久化物件;而load方法會在呼叫後返回一個代理物件,該代理物件只儲存了實體物件的id,直到使用物件的非主鍵屬性時才會發出sql語句。
  • load()方法返回的是實體的代理類例項,,而get()方法永遠返回的是實體類
  •  當資料庫中不存在與 OID 對應的記錄時, load() 方法丟擲 ObjectNotFoundException 異常, 而 get() 方法返回 null

4.刪除資料

      (1)Session的delete()方法既可以刪除一個遊離物件,也可以刪除一個持久化物件

      (2)處理過程:

  • 計劃執行一條delete語句
  •  把物件從Session快取中刪除,該物件進入刪除狀態

       (3)Hibernate 的 cfg.xml 配置檔案中有一個 hibernate.use_identifier_rollback 屬性, 其預設值為 false, 若把它設為 true, 將改變 delete() 方法的執行行為: delete() 方法會把持久化物件或遊離物件的 OID 設定為 null, 使它們變為臨時物件

程式碼如下:

package com.Test;

import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;
public class deleteProduct {
    public static void main(String[] args)
    {Session session = null;			//宣告Session物件
        try {
            //Hibernate的持久化操作
            session = HibernateInitialize.getSession();//獲取Session
            session.beginTransaction();
            Product product = (Product) session.get(Product.class, new Integer("0"));//裝載物件
            session.delete(product);//刪除持久化資訊
            session.getTransaction().commit();
        } catch (Exception e) {
            System.out.println("物件刪除失敗");
            e.printStackTrace();
        } finally{
            HibernateInitialize.closeSession();//關閉Session
        }
    }
}
截圖如下:


資料庫表截圖:


注意:在剛增加,查詢時都沒有開啟事務,提交事務,不會報錯。但在delete()方法中,是對持久化物件進行刪除,當持久化物件發生改動時並不會立即執行資料庫操作,只有當事務結束時,才會更新資料庫。所以必須使用事務

5.更新資料

   (1)從資料庫中獲得物件,然後修改屬性,採用Session的flush()方法--是指Session執行一些必需的SQL語句來把記憶體中的物件狀態同步於JDBC中。刷出會在某些查詢之前執行,在事務提交時執行

//Hibernate的持久化操作
			session = HibernateInitialize.getSession();//獲取Session
			Product product = (Product) session.load(Product.class, new Integer("1"));//裝載物件
			product.setName("Java Web程式設計詞典");//修改商品名稱
			product.setRemark("無");//修改備註資訊
			session.update(product );
			session.flush();
  (2)update()方法

   update()方法是一個使一個遊離狀態轉變為持久化物件並且計劃執行一條update語句

  • 若希望 Session 僅當修改了 News 物件的屬性時, 才執行 update() 語句, 可以把對映檔案中 <class> 元素的 select-before-update 設為 true. 該屬性的預設值為 false
  • 當只更新物件一個屬性時,其他屬性也會被改變,可以把對映檔案中 <class> 元素的 dynamic-update設為true
  •  當 update() 方法關聯一個遊離物件時, 如果在 Session 的快取中已經存在相同 OID 的持久化物件, 會丟擲異常
  •  當 update() 方法關聯一個遊離物件時, 如果在資料庫中不存在相應的記錄, 也會丟擲異常. 

程式碼:

package com.Test;

import com.Product.Product;
import com.hibernate.HibernateInitialize;
import org.hibernate.Session;

public class UpdateProduct {
    public static void main(String[] args)
    {
        Session session=null;
        try
        {
            session= HibernateInitialize.getSession();
            session.beginTransaction();
            Product product=(Product)session.get(Product.class,new Integer(0));
            product.setName("Java經典");
            session.update(product);
            session.getTransaction().commit();
        }catch (Exception e)
        {
            e.printStackTrace();
        }finally {
            HibernateInitialize.closeSession();
        }
    }
}
控制檯輸出截圖:


資料庫截圖:


  6.saveOrUpdate()方法

    Session 的 saveOrUpdate() 方法同時包含了 save() 與 update() 方法的功能


  判定物件為臨時物件的標準:

         Java物件的OID為null

          對映檔案中為 <id> 設定了 unsaved-value  屬性, 並且 Java 物件的 OID 取值與這個 unsaved-value 屬性值匹配

7.merge()方法

       新new一個物件,如果該物件設定了ID,則這個物件就當作遊離態處理:
                當ID在資料庫中不能找到時,用update的話肯定會報異常,然而用merge的話,就會insert。
                 當ID在資料庫中能找到的時候,update與merge的執行效果都是更新資料,發出update語句;
       如果沒有設定ID的話,則這個物件就當作瞬態處理:
                 用update的話,由於沒有ID,所以會報異常,merge此時則會儲存資料,根據ID生產策略生成一條資料;