Hibernate系列之核心開發接口


一、概述

  所有的hibernate應用中都會訪問5個核心接口,它們分別是:

  • Configuration:配置hibernate,創建SessionFactory對象
  • SessionFactory:初始化hibernate,充當數據存儲源的代理,創建Session對象
  • Session:負責保存、更新、刪除、加載和查詢對象
  • Transaction:管理事事務
  • Query和Criteria:執行數據庫查詢

  下面將對這五個接口進行逐一總結:  

二、Configuration

  一個Configuration的實例允許應用指定在創建一個SessionFactory時使用的屬性和映射文件,通常一個應用將創建一個單獨的Configuration,構建一個SessionFactory的單一實例然后實例化會話線程用於服務客戶請求。Configuration僅僅是作為一個初始化時的對象,一個Configeration 實例代表Hibernate 所有Java類到Sql數據庫映射的集合。

  Configuration主要用於產生SessionFactory,進行配置信息的管理,可以在configure方法中指定hibernate文件。

  在Hibernate 4之前的版本中,Configuration是通過下述方式產生SessionFactory的:

SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory();

  Hibernate 4以后,Configuration的buildSessionFactory方法被標記為過時,官方建議使用buildSessionFactory(ServiceRegistry sr)這個方法來獲取SessionFactory。

 Configuration configuration = new Configuration().configure(); 
 ServiceRegistry sr=new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
 SessionFactory sessionFactory = configuration.buildSessionFactory(sr); 

三、SessoinFactory

  SessionFactory的主要作用是產生和管理Session,通常情況下每一個應用只需要一個SessionFactory,當需要操作多個數據庫時,可以為每個數據庫指定一個SessionFactory。

  一個SessionFactory的內部狀態是不可變的,一旦創建了這個內部狀態的內部設置便不再與Configuration對象關聯,這種狀態包括所有關於對象/關系映射數據。

  SessionFactory在Hibernate中起到一個緩沖區的作用,它緩沖了Hibernate自動生成的SQL語句和一些其他的映射數據。

  SessionFactory可以通過兩種方法getCurrentSession()和openSession()產生Session,兩種方法的區別有:

  1. openSession每次打開都是新的Session,並且需要人為的調用close方法關閉Session。
  2. getCurrentSession是從當前上下文中獲取Session並且會綁定到當前線程,第一次調用會自動創建一個Session實例,如果未手動關閉多次獲取的是同一個Session,事物提交或者回滾時會自動關閉Session。
  3. 使用getCurrentSession時,需要在配置文件中添加如下:

  (1)如果使用的是本地事務(JDBC事務)

 <property name="current_session_context_class">thread</property>

  (2)如果使用的是全局事務(JTA事務)

<property name="current_session_context_class">jta</property>

  備注:

  全局事務:資源管理器管理和協調的事務,可以跨越多個數據庫和進程。資源管理器一般使用XA 二階段提交協議與“企業信息系統”(EIS) 或數據庫進行交互。   

  本地事務:在單個 EIS或數據庫的本地並且限制在單個進程內的事務。本地事務不涉及多個數據來源。

  使用getCurrentSession()方法時,如果未配置上述屬性,則會報錯:

  

四、Session

  Session用於管理一個數據庫的任務單元(增、刪、改、查),它是Java應用和Hibernate之間主要運行接口,是抽象持久性服務概念的主要API。

  Session的生命周期是以一個邏輯事物的開始和結束為邊界,Session的主要功能是提供創建、讀取和刪除映射的實體類的操作,實體可能存在於三種狀態:

  1. 瞬時狀態(transient)

  即為普通的Java對象,此狀態下,不與Session實例關聯,在數據庫中沒有和瞬時對象關聯的數據

  2.  持久狀態(persistent)

  處於此狀態的實例在數據庫中對應的記錄,並擁有一個持久化標識。持久狀態的對象總是與Session和Transaction相關聯,在一個Session中,對持久對象的改變不會馬上對數據庫進行變更,而是發生在Transaction終止,執行commit之后。

  3.  游離狀態(detached)

  與持久狀態的對象關聯的Session被關閉后,該對象就變成游離狀態,此狀態下對游離對象的引用依然有效,也可以繼續被修改。

   這三種狀態之間可以相互轉換,如下圖示:

  

  Session中有一個緩存,被稱為hibernate的第一季緩存,它存放被當前工作單元加載的對象,這塊緩存中有一map,在執行save方法后,會生成一個id,這個id會保存在map的key中,與之對應的value值就是該是該對象的引用,執行commit()方法后,數據庫就有對應這條數據了,此時該實體處於持久化狀態,當執行完Session.close()后,處於托管狀態。

  區分這三種狀態的關鍵在於:

  • 有沒有ID
  • ID在數據庫中有沒有
  • 在內存中沒有

  瞬時狀態下,為內存中一個對象沒有ID,緩存中也沒有

  持久化狀態,內存有,緩存中有,數據庫中也存在

  托管狀態:內存中有,緩存中沒有,數據庫中存在ID

  Session接口有幾個重要的方法:

  save():持久化給出的瞬時狀態的實體,並分配有一個ID標識符

@Test
    public void test()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        Book b=new Book();
        b.setBookName("Java");
        b.setId(1);
        b.setPrice(21);
        session.beginTransaction();
        session.save(b);
        session.getTransaction().commit();    
    }

  Delete():從數據庫中刪除持久化實體

@Test
    public void test()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Book b=(Book) session.get(Book.class, 1);
        session.delete(b);
        session.getTransaction().commit();    
    }

  load():返回給定標識符的實體類的持久化實例(假定實例存在),不能使用該方法來確定一個實例是否存在(使用get方法)

@Test
    public void test()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Book b=(Book) session.load(Book.class, 1);
        System.out.println(b.getBookName());
        session.getTransaction().commit();      
    }

  get():返回給定標識符的實體類的持久化實例或null(如果實例不存在)

@Test
    public void test()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Book b=(Book) session.get(Book.class, 1);
        session.getTransaction().commit();      
        System.out.println(b.getBookName());
    }

  get()和load()方法的區別

  1. 當對應記錄不存在時,使用load方法會報異常,而get方法會返回null

  

  

  2.  load返回的是代理對象,等到真正用到對象的內容時才發出sql語句,而get直接從數據庫加載,不會延遲

  update():更新指定標識符的托管狀態實例為持久化狀態,如果存在具有相同標識符的持久化實例,將會報異常

五、Transaction

  Hibernate的Transaction是底層的JDBC Transaction或者JTA Transaction的封裝,具體取決於在hibernate.properties中的配置。

  一個典型的事務在創建完Session對象后即使用beginTransaction()啟動事務,從此開始知道commit()之間的代碼都會處於同一個事務中,這兩個函數之間的所有的數據庫代碼都會在commit()執行時一次性提交,在提交時如果某一句代碼執行出現異常,就會回滾這一次事務之間的所有執行代碼。

六、Query

   通過SessionFactory獲得了session對象后,除了可以通過get(類名.class, id)方法得到相應的對象,還可以通過獲得Query對象來取得需要的對象:

  Query query = session.createQuery("查詢語句如from UserBean");
    List list = query.list();//得到一個集合
  query.uniqueResult();//得到一個單個的對象

    分頁查詢:

   query.setFirstResult(位置);//表示從哪個位置開始查詢,返回query對象
   query.setMaxResult(記錄條數);//表示當頁共幾條記錄,返回一個集合
   session.createQuery("select count(*) from 類名").uniqueResult();//得到記錄總數

  查詢語句同sql查詢語句很相像,只是將表名換作類名,字段名換作屬性名,如果查詢需要條件可以使用占位符來替換對應的屬性名,也可以使用:變量名來作為占位符。

  eg:

@Test
    public void test1()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query q=(Query) session.createQuery("from Person");
        List<Person> persons=(List<Person>)q.list();
        for(Person p:persons)
            System.out.println(p.getName());
        session.getTransaction().commit();
    }
public void test2()
    {
        Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query q=(Query) session.createQuery("select count(*) from Person");//得到記錄總數
        int count=((Long)q.uniqueResult()).intValue();
        System.out.println(count);
        session.getTransaction().commit();
    }

 


免責聲明!

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



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