欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

全面解析Hibernate關(guān)聯(lián)操作、查詢(xún)操作、高級(jí)特性、并發(fā)處理機(jī)制

 更新時(shí)間:2016年06月17日 09:18:18   作者:皮卡丘啾啾  
這篇文章主要介紹了全面解析Hibernate關(guān)聯(lián)操作、查詢(xún)操作、高級(jí)特性、并發(fā)處理機(jī)制的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

本文所需的數(shù)據(jù)庫(kù)初始文件,Hibernate常用操作的完整示例代碼(包含所有Hibernate操作所需jar文件)提供下載學(xué)習(xí):http://download.csdn.net/detail/daijin888888/9551724

1、Hibernate關(guān)聯(lián)映射  

  1)什么是關(guān)聯(lián)映射?

        如果表之間具有關(guān)聯(lián)關(guān)系,Hibernate允許我們?cè)趆bm.xml中描述他們的關(guān)聯(lián)關(guān)系,然后在我們操作其中一張表時(shí),自動(dòng)的根據(jù)這種關(guān)系操作到另外的關(guān)系表,那么這種關(guān)聯(lián)關(guān)系的設(shè)置,我們稱(chēng)之為關(guān)聯(lián)映射。

    2)關(guān)聯(lián)映射的好處?

        一次訪(fǎng)問(wèn)可以關(guān)聯(lián)操作多張表

            --關(guān)聯(lián)查詢(xún)出關(guān)系表的數(shù)據(jù)

            --關(guān)聯(lián)新增、修改關(guān)系表的數(shù)據(jù)

            --關(guān)聯(lián)刪除關(guān)系表的數(shù)據(jù)

    3)關(guān)聯(lián)映射實(shí)現(xiàn)步驟

        --了解表之間的關(guān)系,且明確關(guān)系字段

        --在實(shí)體類(lèi)中追加關(guān)聯(lián)屬性,用于封裝關(guān)聯(lián)的數(shù)據(jù)

        --需要配置hbm.xml文件,設(shè)置關(guān)聯(lián)關(guān)系

*2、一對(duì)多關(guān)聯(lián)    

例:假如一個(gè)Account有多條Service記錄,希望在查詢(xún)account數(shù)據(jù)時(shí),自動(dòng)連帶著查詢(xún)出它對(duì)應(yīng)的service數(shù)據(jù)。

    1)表關(guān)系

        一對(duì)多的關(guān)系,關(guān)系字段是service.account_id。(即Service表中要有與Account表關(guān)聯(lián)的字段account_id,該字段對(duì)應(yīng)Account表中的id)

    2)追加關(guān)系屬性

        在Account類(lèi)中,追加關(guān)聯(lián)屬性services,其類(lèi)型為Set<Service>。

 private Set<Service> services = new HashSet<Service>();

    3)設(shè)置關(guān)聯(lián)關(guān)系

        --語(yǔ)法

            在Account.hbm.xml中,設(shè)置一對(duì)多關(guān)系

   <set name="關(guān)聯(lián)屬性名">
    <key column="關(guān)聯(lián)字段名"/>
    <one-to-many class="關(guān)聯(lián)表的實(shí)體類(lèi)名"/>
   </set>
  --實(shí)現(xiàn)
   <set name="services">
    <key column="account_id"/>
    <one-to-many class="com.*.entity.Service"/>
   </set>

   4)示例代碼

        已知: 

           --關(guān)聯(lián)屬性services

           --關(guān)聯(lián)字段account_id

            --關(guān)聯(lián)對(duì)象Service --> 表名service

<span style="font-size:14px;">public void testFind() { 
 Session session = HibernateUtil.getSession(); 
 Account a = (Account) session.load(Account.class, 1010); 
 System.out.println("---顯示Account賬號(hào)信息---"); 
 System.out.println(a.getId() + " " + a.getRealName() + " " + a.getIdcardNo()); 
 System.out.println("---顯示當(dāng)前賬號(hào)下的業(yè)務(wù)賬號(hào)---"); 
 Set<Service> services = a.getServices(); 
 for (Service s : services) { 
  System.out.println(s.getId() + " " + s.getOsUserName() + " " + s.getUnixHost()); 
 } 
 System.out.println(a.toString()); 
}</span> 

*3、多對(duì)一關(guān)聯(lián) 

   例:希望在查詢(xún)service數(shù)據(jù)后,可以自動(dòng)的查詢(xún)出它對(duì)應(yīng)的account數(shù)據(jù)。

    1)關(guān)聯(lián)關(guān)系 

       service與account具有多對(duì)一的關(guān)系,關(guān)系字段為service.account_id

    2)追加關(guān)聯(lián)屬性

        --在Service實(shí)體類(lèi)中追加關(guān)聯(lián)屬性account,其類(lèi)型為Account。

        private Account account;

           此后accountId屬性可以去掉,可以通過(guò)getAccount().getId()方法來(lái)得到account_id的值

    3)設(shè)置關(guān)聯(lián)關(guān)系

        a、語(yǔ)法:

            --在Service.hbm.xml中,追加關(guān)聯(lián)關(guān)系的配置

            --<many-to-one name="關(guān)聯(lián)屬性名"
                    column="關(guān)系字段名"
                    class="關(guān)聯(lián)表的實(shí)體類(lèi)名"/>

        b、實(shí)現(xiàn):

           <many-to-one name="account"
                column="account_id"
                class="com.*.entity.Account"/>

    4)示例代碼

        已知:

            --關(guān)聯(lián)屬性account

            --關(guān)聯(lián)字段account_id

            --關(guān)聯(lián)對(duì)象Account --> 表名account,主鍵id

<span style="font-size:14px;">public void testFind() { 
 Session session = HibernateUtil.getSession(); 
 Service s = (Service) session.get(Service.class, 2002); 
 System.out.println("----顯示業(yè)務(wù)賬號(hào)信息---"); 
 System.out.println(s.getId() + " " + s.getOsUserName() + " " + s.getUnixHost()); 
 System.out.println("----顯示相關(guān)賬務(wù)賬號(hào)信息---"); 
 System.out.println(s.getAccount().getId() + " " + s.getAccount().getRealName()); 
}</span> 

*4、關(guān)聯(lián)操作   

 1)關(guān)聯(lián)查詢(xún)

        如果需要當(dāng)前對(duì)象和關(guān)聯(lián)屬性一起采用一個(gè)SQL語(yǔ)句實(shí)例化,可以采用下面方法:

       a、(不推薦)修改hbm.xml中的關(guān)聯(lián)屬性映射

        lazy屬性:

            true表示啟用延遲加載;

            false表示關(guān)閉延遲加載

        fetch屬性:

            join表示采用連接方法與主對(duì)象一起查詢(xún),此時(shí),lazy="false"失效;

            select(默認(rèn))表示單獨(dú)發(fā)送一個(gè)SQL查詢(xún)關(guān)聯(lián)數(shù)據(jù)

        b、(推薦)通過(guò)HQL及join fetch語(yǔ)法

            --from Account a join fetch a.services where a.id=?

            含義:在查詢(xún)Account對(duì)象時(shí),將services關(guān)聯(lián)屬性數(shù)據(jù)采用表連接方式一并查出來(lái)。

            --from Service s join fetch s.account where s.id=?

            含義:在查詢(xún)Service對(duì)象時(shí),將account關(guān)聯(lián)屬性數(shù)據(jù)采用表連接方式一并查出來(lái)。

            --from Service s join fetch s.account where s.account.id=?

        注意:

            --HQL中寫(xiě)的是對(duì)象和屬性

            --join fetch后面沒(méi)有on子句,而fetch的是關(guān)聯(lián)屬性
            --query.setInteger來(lái)設(shè)置整型參數(shù)值,下標(biāo)從0開(kāi)始。

            --如果明確該HQL只會(huì)返回一條記錄,可以使用query.uniqueResult()方法返回唯一的記錄

        c、示例代碼(改寫(xiě)上述一對(duì)多關(guān)聯(lián)的查詢(xún)代碼)

<span style="font-size:14px;">public void testFind() { 
 Session session = HibernateUtil.getSession(); 
 // Account a = (Account) session.load(Account.class, 1010); 
 String hql = "from Account a join fetch a.services where a.id=?"; 
 Query query = session.createQuery(hql); 
 query.setInteger(0, 1010);// ?從0開(kāi)始 
 Account a = (Account) query.uniqueResult();// 單行查詢(xún)可采用 
 System.out.println("---顯示Account賬號(hào)信息---"); 
 System.out.println(a.getId() + " " + a.getRealName() + " " + a.getIdcardNo()); 
 System.out.println("---顯示當(dāng)前賬號(hào)下的業(yè)務(wù)賬號(hào)---"); 
 Set<Service> services = a.getServices(); 
 for (Service s : services) { 
  System.out.println(s.getId() + " " + s.getOsUserName() + " " + s.getUnixHost()); 
 } 
 System.out.println(a.toString()); 
}</span> 

   2)級(jí)聯(lián)添加、級(jí)聯(lián)修改

        a、當(dāng)表具有關(guān)聯(lián)關(guān)系時(shí),Hibernate不僅僅提供關(guān)聯(lián)查詢(xún)的功能,還具有關(guān)聯(lián)添加、修改、刪除關(guān)聯(lián)表中數(shù)據(jù)的能力,這種能力稱(chēng)之為級(jí)聯(lián)操作。

       b、如何實(shí)現(xiàn)級(jí)聯(lián)操作

            需要在關(guān)聯(lián)屬性設(shè)置的位置,追加屬性cascade

            --none:默認(rèn)不支持級(jí)聯(lián)

            --save-update:支持級(jí)聯(lián)添加與更新

            --delete:支持級(jí)聯(lián)刪除

            --all:支持級(jí)聯(lián)添加、更新、刪除

        c、說(shuō)明

            通常1對(duì)多的表關(guān)系,1的一方是主表,多的一方是從表,往往是需要在添加、更新、刪除主表時(shí)連帶添加、更新、刪除從表的數(shù)據(jù)。如:刪除賬務(wù)賬號(hào)時(shí),要連帶刪除業(yè)務(wù)賬號(hào)的數(shù)據(jù)

    3)級(jí)聯(lián)刪除

        a、設(shè)置cascade="delete"或cascade="all"就可以支持級(jí)聯(lián)刪除

        b、通常情況下,需要在1的一方set標(biāo)簽處,追加屬性inverse="true"

        c、session.delete(obj);obj需要是持久對(duì)象,不能new,需要load/get取出

        d、批量刪除的方法:

        級(jí)聯(lián)刪除采用n+1個(gè)delete語(yǔ)句清除主表和外鍵表的關(guān)聯(lián)數(shù)據(jù)。

        如果是批量刪除,不推薦級(jí)聯(lián)刪除,建議采用HQL編寫(xiě)delete刪除語(yǔ)句。

        delete from Service where account.id=?//刪除Service表中所有account.id=?的數(shù)據(jù),(該句替代級(jí)聯(lián)操作中的n個(gè)delete語(yǔ)句)

        delete from Account where id=?

    4)inverse屬性(理解)詳細(xì)說(shuō)明點(diǎn)這里

        是否交出關(guān)系維護(hù)的控制權(quán)。即默認(rèn)情況下,Account和Service對(duì)象之間的關(guān)系由雙方負(fù)責(zé)維護(hù)。意思是對(duì)Account或Service對(duì)象做級(jí)聯(lián)操作時(shí),需要執(zhí)行update語(yǔ)句將關(guān)聯(lián)字段設(shè)置成相同ID。如果需要取消某一方的關(guān)系維護(hù)工作,可以在關(guān)聯(lián)屬性部分添加inverse="true"設(shè)置,這樣可以避免update語(yǔ)句執(zhí)行。

        true:交出控制權(quán),當(dāng)前的對(duì)象不負(fù)責(zé)維護(hù)兩張表的關(guān)聯(lián)關(guān)系

        false:不交出控制權(quán),當(dāng)前的對(duì)象要負(fù)責(zé)維護(hù)兩張表的關(guān)聯(lián)關(guān)系

        提示:往往是一的一方(即<one-to-many>映射部分)設(shè)置為inverse="true",這樣在對(duì)一方級(jí)聯(lián)操作時(shí),可以避免大量的update更新語(yǔ)句。

*5、多對(duì)多關(guān)聯(lián)

    例:管理員admin_info和角色role_info具有多對(duì)多的關(guān)系,希望在查詢(xún)管理員時(shí)能夠連帶著查詢(xún)出他對(duì)應(yīng)的角色。 數(shù)據(jù)庫(kù)設(shè)計(jì)時(shí),需采用3張表表示。

    ADMIN_INFO(管理員)

   ADMIN_ROLE(管理員和角色關(guān)系)

    ROLE(角色)

    1)關(guān)系字段

        關(guān)系字段位于他們的中間表admin_role中,

        admin_id=admin_info.id

        role_id=role_info.id

    2)追加關(guān)聯(lián)屬性在管理員的實(shí)體類(lèi)中追加角色相關(guān)屬性

        Set<Role> roles

    3)在Admin.hbm.xml中追加關(guān)聯(lián)映射配置

--語(yǔ)法
    <set name="關(guān)聯(lián)屬性名" table="中間表名">
      <key column="Admin的關(guān)聯(lián)字段名"/>
      <many-to-many class="關(guān)聯(lián)表的實(shí)體類(lèi)名"
        column="關(guān)聯(lián)表的關(guān)系字段名"/>
    </set>
    --代碼
    <set name="roles" table="admin_role">
      <key column="admin_id"/>
      <many-to-many class="com.*.entity.Role"
        column="role_id"/>
    </set>

    4)級(jí)聯(lián)操作

        cascade表示支持級(jí)聯(lián)操作,操作的是另一方的表,而并不是表示級(jí)聯(lián)操作中間表。對(duì)于中間表的維護(hù),不需要寫(xiě)cascade屬性。

    5)inverse

        通常情況下,多對(duì)多關(guān)聯(lián),不需要寫(xiě)inverse="true",原因是另一方在插入數(shù)據(jù)時(shí),可能沒(méi)有管中間表的數(shù)據(jù),需要當(dāng)前的一方來(lái)維護(hù),因此不能寫(xiě)inverse="true",否則的話(huà),雙方都不維護(hù)這個(gè)關(guān)系,數(shù)據(jù)上有問(wèn)題。

    6)示例Java代碼

<span style="font-size:14px;">    // 移除角色 
  @Test 
  public void testDeleteRole() { 
    Session session = HibernateUtil.getSession(); 
    Transaction tx = session.beginTransaction(); 
    try { 
      Admin a = (Admin) session.load(Admin.class, 1); 
      Role r1 = (Role) session.load(Role.class, 1); 
      a.getRoles().remove(r1); 
      session.update(a); 
      tx.commit(); 
    } catch (HibernateException e) { 
      e.printStackTrace(); 
      tx.rollback(); 
    } finally { 
      session.close(); 
    } 
  } 
  // 追加角色 
  @Test 
  public void testAddRole() { 
    Session session = HibernateUtil.getSession(); 
    Transaction tx = session.beginTransaction(); 
    try { 
      Admin a = (Admin) session.load(Admin.class, 1); 
      Role r1 = (Role) session.load(Role.class, 1); 
      Role r2 = (Role) session.load(Role.class, 43); 
      Role r3 = (Role) session.load(Role.class, 44); 
      a.getRoles().add(r1); 
      a.getRoles().add(r2); 
      a.getRoles().add(r3); 
      session.update(a); 
      tx.commit(); 
    } catch (HibernateException e) { 
      e.printStackTrace(); 
      tx.rollback(); 
    } finally { 
      session.close(); 
    } 
  } 
  @Test 
  public void testFind() { 
    Session session = HibernateUtil.getSession(); 
    Transaction tx = session.beginTransaction(); 
    try { 
      Admin a = (Admin) session.load(Admin.class, 1); 
      System.out.println("----顯示管理員信息---"); 
      System.out.println(a.getId() + " " + a.getName() + " " 
          + a.getTelephone()); 
      System.out.println("----顯示管理員角色信息---"); 
      for (Role role : a.getRoles()) { 
        System.out.println(role.getName() + " "); 
      } 
      tx.commit(); 
    } catch (HibernateException e) { 
      e.printStackTrace(); 
      tx.rollback(); 
    } finally { 
      session.close(); 
    } 
  }</span> 

6、繼承關(guān)聯(lián)

    例:在電商網(wǎng)站上搜索商品,比如輸入iphone來(lái)搜索,搜索結(jié)果中可以包含手機(jī)、手機(jī)膜、手機(jī)殼、充電器、耳機(jī)等等相關(guān)的產(chǎn)品信息。這種功能,我們可以在設(shè)計(jì)表時(shí)用一種特殊的一對(duì)一的關(guān)系來(lái)表現(xiàn)。即將所有商品通用的屬性提取到一張公共的表中product,具體商品表中只保存該商品特有的屬性,那么具體商品表和product表具有一對(duì)一的關(guān)系。在搜索時(shí)只搜索product表,就可以將相關(guān)的信息模糊查找出來(lái)。

        --通用信息表product(id,name,price,desc)

        --書(shū)的商品表book(id,authod,publishing,words)

        --希望在操作book表時(shí),能夠自動(dòng)的將通用的字段維護(hù)到product表中。

    1)明確表的關(guān)系

        book與product具有一對(duì)一的關(guān)系,這種關(guān)系的目的是為了復(fù)用product表中的字段,像是一種繼承關(guān)系

    2)實(shí)體類(lèi)

        Book extends Product

    3)配置文件中體現(xiàn)關(guān)聯(lián)關(guān)系

        --父類(lèi)型同原先的配置文件寫(xiě)法一致

        --子類(lèi)型具有特殊性

    <joined-subclass 
        name="類(lèi)型名" table="表名" 
        extends="父類(lèi)名稱(chēng)">
        <key column="關(guān)聯(lián)字段名"/>
        <property name="" type="" column=""/>
        ...
      </joined-subclass>

    4)繼承關(guān)系中,由于2張表具有類(lèi)似于父子的關(guān)系,那么子表中必須引用父表中的數(shù)據(jù),不存在不引用的情況,即必須在維護(hù)子表同時(shí)維護(hù)父表。所以這是固定的情況,就不用寫(xiě)cascade,inverse。

    5)描述類(lèi)別(了解)

        <joined-subclass>數(shù)據(jù)庫(kù)有父類(lèi)表和子類(lèi)表
        <union-subclass>數(shù)據(jù)庫(kù)有子類(lèi)表、沒(méi)有父類(lèi)表(子類(lèi)表已包含父類(lèi)表字段,無(wú)父類(lèi)表,但有父類(lèi)實(shí)體對(duì)象)
        <subclass>數(shù)據(jù)庫(kù)有父類(lèi)子類(lèi)都用一個(gè)表(設(shè)計(jì)較亂,即沒(méi)有進(jìn)行表拆分,很少用)

*7、Hibernate查詢(xún)

    1)*HQL查詢(xún)(Hibernate Query Language)

       屬于面向?qū)ο蟛樵?xún)語(yǔ)句,針對(duì)Hibernate映射過(guò)來(lái)的POJO進(jìn)行查詢(xún),從而實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的查詢(xún)。

       a、以非主鍵做條件查詢(xún)

            --條件參數(shù)以?表示,query.setString(0,"");

            --條件參數(shù)以:x表示,query.setString("x","");

            示例代碼:

<span style="font-size:14px;">    // 測(cè)試按非主鍵做條件查詢(xún) 
  @Test 
  public void testFind1() { 
    String hql = "from Service where account.id=? and unixHost=?"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    query.setInteger(0, 1011); 
    query.setString(1, "192.168.0.23"); 
    List<Service> list = query.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  } 
  // 等價(jià)于testFind1,采用“:標(biāo)識(shí)符”替代 
  @Test 
  public void testFind2() { 
    String hql = "from Service where account.id=:aid and unixHost=:host"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    query.setInteger("aid", 1011); 
    query.setString("host", "192.168.0.23"); 
    List<Service> list = query.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  }</span> 

       b、只查詢(xún)一部分屬性

            --默認(rèn)返回的集合中封裝的是Object[]
            --new Service(id,unixHost,osUserName)使返回的結(jié)合中封裝的是Service對(duì)象,

                注意:

                    Service中需要追加響應(yīng)的構(gòu)造器;

                    不要丟掉無(wú)參構(gòu)造器;

            示例代碼:

<span style="font-size:14px;">    // 獲取部分字段結(jié)果,默認(rèn)采用Object[]封裝數(shù)據(jù) 
  @Test 
  public void testFind3() { 
    String hql = "select s.id,s.unixHost,s.osUserName from Service s where s.account.id=?"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    query.setInteger(0, 1011); 
    List<Object[]> list = query.list(); 
    for (Object[] objs : list) { 
      System.out.println(objs[0] + " " + objs[1] + " " + objs[2] + " "); 
    } 
    session.close(); 
  } 
  // 等價(jià)于testFind3,需要添加對(duì)應(yīng)的構(gòu)造方法 
  @Test 
  public void testFind4() { 
    String hql = "select new Service(s.id,s.unixHost,s.osUserName) from Service s where s.account.id=?"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    query.setInteger(0, 1011); 
    List<Service> list = query.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  }</span> 

       c、HQL定義在配置文件中(了解即可)

           --通過(guò)query元素在配置文件中定義HQL
            --query元素寫(xiě)在class的后面
            --session.getNamedQuery(HQL名);

            示例代碼:<query/>與<class/>在hbm.xml中同級(jí)擺放

<span style="font-size:14px;"><query name="findAll"><!-- CDATA內(nèi)包括純文本字段,防止出現(xiàn)特殊字符 --> 
  <![CDATA[ 
  from Service 
  ]]> 
  </query></span> 
<span style="font-size:14px;">    // 將HQL定義到hbm.xml中(只適用靜態(tài)HQL語(yǔ)句結(jié)構(gòu)) 
  @Test 
  public void testFind5() { 
    Session session = HibernateUtil.getSession(); 
    // 獲取hbm.xml中<query>定義的hql語(yǔ)句 
    Query query = session.getNamedQuery("findAll"); 
    List<Service> list = query.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  }</span> 

       d、分頁(yè)查詢(xún)

            --查詢(xún)記錄

                query.setFirstResult((page-1)*pageSize);

                query.setMaxResults(pageSize);

            --查詢(xún)總頁(yè)數(shù)

                select count(*) from Service

            示例代碼:

<span style="font-size:14px;">    // 測(cè)試分頁(yè)查詢(xún) 
  @Test 
  public void testFind6() { 
    int page = 2; 
    String hql = "from Service order by id"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    // 追加分頁(yè)參數(shù)設(shè)置 
    query.setFirstResult((page - 1) * 3);// 設(shè)置抓起記錄的起點(diǎn),從0開(kāi)始 
    query.setMaxResults(3);// 設(shè)置最大抓取數(shù)量 
    List<Service> list = query.list();// 執(zhí)行查詢(xún),如果沒(méi)有分頁(yè)設(shè)置就查所有值 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  } 
  // select count(*) from SERVICE 
  @Test 
  public void testFind7() { 
    String hql = "select count(*) from Service"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    Long size = (Long) query.uniqueResult(); 
    System.out.println("記錄總數(shù):" + size); 
    session.close(); 
  }</span> 

       e、關(guān)聯(lián)查詢(xún)(記住一種即可)

            --from Service s,Account a

                where s.account.id=a.id

            --from Service s inner join s.account a

            --select s.account.realName from Service s

       總結(jié):

        HQL與SQL的相同點(diǎn): 

           --支持select,from,where,group,order by子句

            --支持inner join,left join等連接

            --支持>,<,>=,<=,in,not in,between,like等條件

            --支持分組統(tǒng)計(jì)函數(shù)count,sum,max,min,avg

        HQL與SQL的不同點(diǎn)

            --HQL語(yǔ)句區(qū)分大小寫(xiě),即大小寫(xiě)敏感。關(guān)鍵字不區(qū)分。

            --HQL中寫(xiě)的是對(duì)象名和屬性名,而不是表名和字段名

            --不支持join on中的on子句

            --不支持select *

            --不支持?jǐn)?shù)據(jù)庫(kù)函數(shù),比如日期函數(shù)to_date()、字符函數(shù)to_char()等

    2)Criteria查詢(xún)(不夠直觀,了解即可)

        使用Hibernate的API來(lái)拼一個(gè)HQL

        Criteria c = session.createCriteria(Service.class);

           示例代碼:

<span style="font-size:14px;">    // 使用Hibernate的API來(lái)拼一個(gè)HQL 
  @Test 
  public void testFind1() { 
    Session session = HibernateUtil.getSession(); 
    Criteria c = session.createCriteria(Service.class); 
    c.add(Restrictions.and(Restrictions.like("osUserName", "huang%"), 
        Restrictions.eq("unixHost", "192.168.0.26")));// 追加查詢(xún)條件 
    List<Service> list = c.list();// 執(zhí)行查詢(xún),如果沒(méi)有分頁(yè)設(shè)置就查所有值 
    c.addOrder(Order.desc("id"));// 追加排序 
    // c.setFirstResult(arg0);//分頁(yè) 
    // c.setMaxResults(arg0); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName() + " " 
          + s.getUnixHost()); 
    } 
    session.close(); 
  }</span> 

    3)SQL查詢(xún)

       直接幫助我們調(diào)用JDBC來(lái)執(zhí)行SQL查詢(xún)

        SQLQuery sqlQuery = session.createSQLQuery(sql);

            示例代碼:

<span style="font-size:14px;">    @Test 
  public void testFind1() { 
    String sql = "select * from Service"; 
    Session session = HibernateUtil.getSession(); 
    SQLQuery sqlQuery = session.createSQLQuery(sql); 
    sqlQuery.setFirstResult(0);// 分頁(yè) 
    sqlQuery.setMaxResults(3); 
    // 默認(rèn)采用數(shù)組封裝一條記錄 
    List<Object[]> list = sqlQuery.list(); 
    for (Object[] objs : list) { 
      System.out.println(objs[0] + " " + objs[2]); 
    } 
    session.close(); 
  } 
  //同testFind1(),指定封裝記錄的實(shí)體 
  @Test 
  public void testFind2() { 
    String sql = "select * from Service"; 
    Session session = HibernateUtil.getSession(); 
    SQLQuery sqlQuery = session.createSQLQuery(sql); 
    sqlQuery.setFirstResult(0);// 分頁(yè) 
    sqlQuery.setMaxResults(3); 
    // 指定封裝記錄的實(shí)體類(lèi) 
    sqlQuery.addEntity(Service.class); 
    // 采用指定的Service類(lèi)型封裝一條記錄 
    List<Service> list = sqlQuery.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName()); 
    } 
    session.close(); 
  }</span> 

8、Hibernate高級(jí)特性(了解)

    1)二級(jí)緩存

       a、二級(jí)緩存(默認(rèn)關(guān)閉)

            --二級(jí)緩存是SessionFactory級(jí)別的緩存,由SessionFactory負(fù)責(zé)管理

            --緩存的也是實(shí)體對(duì)象
            --緩存數(shù)據(jù)可以被不同的Session間共享
            --適用環(huán)境:對(duì)象數(shù)據(jù)頻繁共享;對(duì)象數(shù)據(jù)變化頻率小

        b、二級(jí)緩存的使用步驟
            --導(dǎo)緩存包ehcache.jar
            --導(dǎo)入緩存配置文件ehcache.xml
            --在hibernate.cfg.xml中,設(shè)置開(kāi)啟二級(jí)緩存,并且設(shè)置緩存驅(qū)動(dòng)類(lèi)

<span style="font-size:14px;"><!-- 使用二級(jí)緩存 --> 
<property name="hibernate.cache.use_second_level_cache">true</property> 
<!-- 指定二級(jí)緩存組件的驅(qū)動(dòng)類(lèi)ehcache.jar --> 
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property></span> 

           --在要緩存的POJO的關(guān)系映射文件hbm.xml中設(shè)置元素<cache usage="readonly"/>

       示例代碼:

<span style="font-size:14px;"><span style="font-size:14px;">    @Test 
  public void testFind1() { 
    // 第一次查詢(xún),使用session1 
    Session session1 = HibernateUtil.getSession(); 
    Service s1 = (Service) session1.get(Service.class, 2002); 
    System.out.println(s1.getOsUserName() + " " + s1.getUnixHost()); 
    session1.close(); 
    // 第二次查詢(xún),使用session2(配置二級(jí)緩存后,兩次查詢(xún)均到二級(jí)緩存中取數(shù)據(jù)) 
    // HibernateUtil.getSessionFactory().evict(Service.class);// 移除后則還是查詢(xún)兩次 
    Session session2 = HibernateUtil.getSession(); 
    Service s2 = (Service) session2.get(Service.class, 2002); 
    System.out.println(s2.getOsUserName() + " " + s2.getUnixHost()); 
  }</span></span> 

    2)查詢(xún)緩存

        a、查詢(xún)緩存

            一級(jí)和二級(jí)緩存只能是緩存單個(gè)對(duì)象。如果遇到某個(gè)字符串結(jié)果、數(shù)組結(jié)果或者List集合,可以使用查詢(xún)緩存存儲(chǔ)。
            --可以看成是特殊的二級(jí)緩存
            --使用的是二級(jí)緩存的緩存空間
            --緩存的是除實(shí)體對(duì)象之外的數(shù)據(jù)類(lèi)型
            --依賴(lài)于二級(jí)緩存,默認(rèn)是關(guān)閉的,需開(kāi)啟二級(jí)緩存才能使用。

        b、使用步驟

           --開(kāi)啟二級(jí)緩存
            --在hibernate.cfg.xml中設(shè)置開(kāi)啟查詢(xún)緩存

<span style="font-size:14px;"><!-- 開(kāi)啟查詢(xún)緩存 --> 
<property name="hibernate.cache.use_query_cache">true</property></span> 

            --query.list()查詢(xún)之前,設(shè)置允許進(jìn)行查詢(xún)緩存,query.setCacheable(true);

        c、使用環(huán)境

            --需要頻繁執(zhí)行的相同的查詢(xún)語(yǔ)句
            --查詢(xún)結(jié)果集內(nèi)容改變頻率小
            --結(jié)果集數(shù)據(jù)量不要太多
        提示:相同的SQL,第一次去數(shù)據(jù)庫(kù)查詢(xún),后續(xù)幾次從緩存取出。因?yàn)榫彺娴氖荢QL+結(jié)果集內(nèi)容

         示例代碼:

<span style="font-size:14px;"><span style="font-size:14px;">    @Test 
  public void testFind() { 
    find(); 
    System.out.println("-------"); 
    find(); 
  } 
  private void find() { 
    String hql = "from Service where account.id=?"; 
    Session session = HibernateUtil.getSession(); 
    Query query = session.createQuery(hql); 
    query.setInteger(0, 1011); 
    // 啟用查詢(xún)緩存執(zhí)行 
    query.setCacheable(true); 
    List<Service> list = query.list(); 
    for (Service s : list) { 
      System.out.println(s.getId() + " " + s.getOsUserName()); 
    } 
  }</span></span> 

9、Hibernate并發(fā)處理-加鎖

    舉例:

        模擬12306購(gòu)票機(jī)制,假設(shè)當(dāng)前有一張火車(chē)票的表tickets(id,line,amount,version),模擬多人同時(shí)購(gòu)票的場(chǎng)景。

    1)悲觀鎖

        --程序悲觀的認(rèn)為,每個(gè)訪(fǎng)問(wèn)者都存在并發(fā)的問(wèn)題,于是會(huì)對(duì)每條數(shù)據(jù)加鎖,那么只有當(dāng)前持有鎖的訪(fǎng)問(wèn)者釋放該鎖時(shí),下一個(gè)訪(fǎng)問(wèn)者才能訪(fǎng)問(wèn)數(shù)據(jù),這種機(jī)制稱(chēng)之為悲觀鎖。

        --就是說(shuō)無(wú)論如何都要給一條數(shù)據(jù)加鎖,不管該數(shù)據(jù)是否會(huì)發(fā)生并發(fā)的問(wèn)題。

        --特點(diǎn)

            效率低,安全性高

        --實(shí)現(xiàn):

            get(Class,id,LockMode.UPGRADE)
            select * from emp for update
 

       注:這里利用的是數(shù)據(jù)庫(kù)自帶的for update子句進(jìn)行加鎖,并非是Hibernate自己發(fā)明的加鎖機(jī)制。

    2)樂(lè)觀鎖

       --程序樂(lè)觀的認(rèn)為,每個(gè)訪(fǎng)問(wèn)者都不會(huì)有并發(fā)的問(wèn)題產(chǎn)生,因此不去加鎖。而是當(dāng)數(shù)據(jù)更新時(shí),判斷該數(shù)據(jù)是否發(fā)生了版本的變化,如果發(fā)生變化,則說(shuō)明在此期間有并發(fā)產(chǎn)生,因此報(bào)錯(cuò)給予提示,本次更新失敗。
        --借助版本字段,當(dāng)?shù)谝粋€(gè)用戶(hù)更新提交后,Hibernate會(huì)將該字段更新加1,這樣后續(xù)用戶(hù)提交的對(duì)象版本字段比數(shù)據(jù)庫(kù)中的小,即在更新時(shí)發(fā)現(xiàn)版本變了,就拋出異常并更新失敗。

        --一個(gè)成功,其他失敗

        --特點(diǎn)

            效率高,用戶(hù)體驗(yàn)差

        --實(shí)現(xiàn)

            a、需要在表中追加版本字段,用于記錄數(shù)據(jù)的版本;

            b、實(shí)體類(lèi)中追加版本屬性;

            c、hbm.xml中追加版本的配置<version name="" type="" column="">

    3)如何選擇

        --如果是并發(fā)量大的情況,應(yīng)選擇樂(lè)觀鎖

        --如果是并發(fā)量小的情況,應(yīng)選擇悲觀鎖

 以上所述是小編給大家介紹的 全面解析Hibernate關(guān)聯(lián)操作、查詢(xún)操作、高級(jí)特性、并發(fā)處理機(jī)制的相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!                  

相關(guān)文章

  • 一文詳解如何更改電腦使用的JDK版本

    一文詳解如何更改電腦使用的JDK版本

    我們?cè)谌粘W(xué)習(xí)或者工作中,難免會(huì)遇到需要使用不同的jdk版本進(jìn)行開(kāi)發(fā),這篇文章主要給大家介紹了關(guān)于如何更改電腦使用的JDK版本的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • Java詳細(xì)分析String類(lèi)與StringBuffer和StringBuilder的使用方法

    Java詳細(xì)分析String類(lèi)與StringBuffer和StringBuilder的使用方法

    當(dāng)對(duì)字符串進(jìn)行修改的時(shí)候,需要使用 StringBuffer 和 StringBuilder類(lèi),和String類(lèi)不同的是,StringBuffer和 StringBuilder類(lèi)的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象
    2022-04-04
  • Java環(huán)境配置與編譯運(yùn)行詳解

    Java環(huán)境配置與編譯運(yùn)行詳解

    這篇文章主要為大家詳細(xì)介紹了Java環(huán)境配置與編譯運(yùn)行的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 從Java到JSON一起探索Jackson的魔力

    從Java到JSON一起探索Jackson的魔力

    Jackson是一個(gè)用于處理JSON數(shù)據(jù)的開(kāi)源Java庫(kù),這篇文章主要為大家介紹了Java是如何利用Jackson處理JSON數(shù)據(jù)的,感興趣的小伙伴可以了解一下
    2023-05-05
  • 詳解Spring Boot最新版優(yōu)雅停機(jī)的方法

    詳解Spring Boot最新版優(yōu)雅停機(jī)的方法

    這篇文章主要介紹了Spring Boot最新版優(yōu)雅停機(jī)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java?C++算法題解leetcode801使序列遞增的最小交換次數(shù)

    Java?C++算法題解leetcode801使序列遞增的最小交換次數(shù)

    這篇文章主要為大家介紹了Java?C++題解leetcode801使序列遞增的最小交換次數(shù)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 一個(gè)JAVA小項(xiàng)目--Web應(yīng)用自動(dòng)生成Word

    一個(gè)JAVA小項(xiàng)目--Web應(yīng)用自動(dòng)生成Word

    前段時(shí)間接到一個(gè)Web應(yīng)用自動(dòng)生成Word的需求,現(xiàn)整理了下一些關(guān)鍵步驟拿來(lái)分享一下。
    2014-05-05
  • RestTemplat中關(guān)于getForobject方法的使用

    RestTemplat中關(guān)于getForobject方法的使用

    這篇文章主要介紹了RestTemplat中關(guān)于getForobject方法的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • java 方法重寫(xiě)與權(quán)限修飾符以及多態(tài)和抽象類(lèi)詳解概念和用法

    java 方法重寫(xiě)與權(quán)限修飾符以及多態(tài)和抽象類(lèi)詳解概念和用法

    重寫(xiě)是子類(lèi)對(duì)父類(lèi)的允許訪(fǎng)問(wèn)的方法的實(shí)現(xiàn)過(guò)程進(jìn)行重新編寫(xiě), 返回值和形參都不能改變。即外殼不變,核心重寫(xiě),權(quán)限修飾符用于控制被修飾變量、方法、類(lèi)的可見(jiàn)范圍,說(shuō)明了面向?qū)ο蟮姆庋b性,所以我們要適用他們盡可能的讓權(quán)限降到最低,從而安全性提高
    2021-10-10
  • SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)的三種方式小結(jié)

    SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)的三種方式小結(jié)

    這篇文章主要介紹了SpringBoot實(shí)現(xiàn)定時(shí)任務(wù)的三種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11

最新評(píng)論