Hibernate 進階

本文包括:

1褐筛、Hibernate的持久化類

2互广、Hibernate 持久化對象的三個狀態(tài)(難點)

3、Hibernate 的一級緩存

4祭饭、Hibernate 中的事務(wù)與并發(fā)

5、Hibernate 的查詢方式(HQL:Hibernate Query Language)

1叙量、Hibernate的持久化類

  • 什么是持久化類倡蝙?

    持久化類:就是一個 Java 類(咱們編寫的 JavaBean),這個 Java 類與表建立了映射關(guān)系就可以成為是持久化類绞佩。

    簡單記:持久化類 = JavaBean + xxx.hbm.xml

  • 持久化類的編寫規(guī)則:

    1. 提供一個無參數(shù) public訪問控制符的構(gòu)造器 —— 底層需要進行反射寺鸥。

    2. 提供一個標識屬性,映射數(shù)據(jù)表主鍵字段 —— 唯一標識 OID征炼,數(shù)據(jù)庫中通過主鍵析既,Java 對象通過地址確定對象,持久化類通過唯一標識 OID 確定記錄谆奥。

    SQL 語句:cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)'

    JavaBean 代碼:private Long cust_id;

    結(jié)論:JavaBean 中的 cust_id 即為唯一標識 OID眼坏。

    1. 所有屬性提供 public 訪問控制符的 set 和 get 方法。

    2. 標識屬性應(yīng)盡量使用基本數(shù)據(jù)類型的包裝類型(默認值為 null)酸些。

  • 自然主鍵和代理主鍵的區(qū)別:

    • 自然主鍵:該主鍵是對象本身的一個屬性宰译。例如:創(chuàng)建一個人員表,每個人都有一個身份證號(唯一的)魄懂。使用身份證號作為表的主鍵沿侈,稱為自然主鍵。(開發(fā)中不會使用這種方式

    • 代理主鍵:該主鍵不是對象本身的一個屬性市栗。例如:創(chuàng)建一個人員表缀拭,為每個人員單獨創(chuàng)建一個字段咳短,用這個字段作為主鍵,稱為代理主鍵蛛淋。(開發(fā)中推薦使用這種方式

    簡單記:創(chuàng)建表時咙好,新增一個毫無關(guān)系的字段,用該字段作為主鍵褐荷。

  • 主鍵的生成策略:

    1. increment:適用于 short,int,long 作為主鍵勾效,沒有使用數(shù)據(jù)庫的自動增長機制。

      • Hibernate 中提供的一種增長機制叛甫,具體步驟如下:

        • 先進行查詢:select max(id) from user;

        • 再進行插入:獲得最大值+1作為新的記錄的主鍵层宫。

      • 問題:不能在集群環(huán)境下或者有并發(fā)訪問的情況下使用。

      分析:在查詢時其监,有可能有兩個用戶幾乎同時得到相同的 id萌腿,再插入時就有可能主鍵沖突!

    2. identity:適用于 short,int,long 作為主鍵棠赛。但是必須使用在有自動增長機制的數(shù)據(jù)庫中哮奇,并且該數(shù)據(jù)庫采用的是數(shù)據(jù)庫底層的自動增長機制。

      • 底層使用的是數(shù)據(jù)庫的自動增長(auto_increment)睛约,像 Oracle 數(shù)據(jù)庫沒有自動增長機制鼎俘,而MySql、DB2 等數(shù)據(jù)庫有自動增長的機制辩涝。
    3. sequence:適用于 short,int,long 作為主鍵贸伐,底層使用的是序列的增長方式。

      • Oracle 數(shù)據(jù)庫底層沒有自動增長,若想自動增長需要使用序列怔揩。
    4. uuid:適用于 char,varchar 類型的作為主鍵捉邢。

      • 使用隨機的字符串作為主鍵.
    5. native:本地策略。根據(jù)底層的數(shù)據(jù)庫不同,自動選擇適用于該種數(shù)據(jù)庫的生成策略(short,int,long)商膊。

      • 如果底層使用的 MySQL 數(shù)據(jù)庫:相當于 identity.

      • 如果底層使用 Oracle 數(shù)據(jù)庫:相當于 sequence.

    6. assigned:主鍵的生成不用 Hibernate 管理了伏伐,必須手動設(shè)置主鍵。

    重點掌握:uuid(字符串)晕拆、native(數(shù)字)

2藐翎、Hibernate 持久化對象的三個狀態(tài)(難點)

  • 持久化對象的狀態(tài)

    1. Hibernate 的持久化類(前文已寫)

    2. Hibernate 的持久化類的狀態(tài)

      • Hibernate為了管理持久化類:將持久化類分成了三個狀態(tài)
        1. 瞬時態(tài):Transient Object

          • 沒有持久化標識 OID, 沒有被納入到 Session 對象的管理(即沒有關(guān)系)
        2. 持久態(tài):Persistent Object

          • 有持久化標識 OID,已經(jīng)被納入到 Session 對象的管理.
        3. 托管態(tài):Detached Object

          • 有持久化標識 OID,沒有被納入到 Session 對象的管理.
  • Hibernate 持久化對象的狀態(tài)的轉(zhuǎn)換

    1. 瞬時態(tài) -- 沒有持久化標識 OID, 沒有被納入到 Session 對象的管理

      • 獲得瞬時態(tài)的對象

          User user = new User();
        

        創(chuàng)建了持久化類的對象,該對象還沒有 OID实幕,也和 Session 對象無關(guān)吝镣,所以是瞬時態(tài)。

      • 瞬時態(tài)對象轉(zhuǎn)換持久態(tài)

          session.save(user); 或者 session.saveOrUpdate(user);
        

        user對象進入緩存昆庇,且自動生成了 OID末贾,故為持久態(tài)。

      • 瞬時態(tài)對象轉(zhuǎn)換成托管態(tài)

          user.setId(1);
        

        手動設(shè)置了 OID整吆,但沒有和 Session 對象發(fā)生關(guān)系拱撵,故為托管態(tài)辉川。

    2. 持久態(tài) -- 有持久化標識OID,已經(jīng)被納入到Session對象的管理

      • 獲得持久態(tài)的對象

          get()/load();
        
      • 持久態(tài)轉(zhuǎn)換成瞬時態(tài)對象

          delete();  --- 比較有爭議的,進入特殊的狀態(tài)(刪除態(tài):Hibernate中不建議使用的)
        
      • 持久態(tài)對象轉(zhuǎn)成脫管態(tài)對象

          session的close()/evict()/clear();
        

        Session 對象被銷毀拴测,所以持久化類的對象沒有被 session 管理员串,所以為托管態(tài)。

    3. 脫管態(tài) -- 有持久化標識OID,沒有被納入到Session對象的管理

      • 獲得托管態(tài)對象:不建議直接獲得脫管態(tài)的對象.

          User user = new User();
          user.setId(1);
        
      • 脫管態(tài)對象轉(zhuǎn)換成持久態(tài)對象

          update();/saveOrUpdate()/lock();
        
      • 脫管態(tài)對象轉(zhuǎn)換成瞬時態(tài)對象

          user.setId(null);
        
    4. 注意:持久態(tài)對象有自動更新數(shù)據(jù)庫的能力!!!

      • 測試代碼:

          /**
           * 持久態(tài)的對象有自動更新數(shù)據(jù)庫的能力
           * session的一級緩存V缈浮!
           */
          @Test
          public void run1(){
              Session session = HibernateUtils.getSession();
              Transaction tr = session.beginTransaction();
              
              // 獲取到持久態(tài)的對象
              User user = session.get(User.class,1);
              // user是持久態(tài)欲诺,有自動更新數(shù)據(jù)庫的能力
              System.out.println(user.getName());
              
              // 重新設(shè)置新的名稱
              user.setName("隔離老王");
              
              // 正常編寫代碼
              // session.update(user);
              
              tr.commit();
              session.close();
          }
        
      • 執(zhí)行后抄谐,控制臺輸出:

          Hibernate: 
              select
                  user0_.id as id1_1_0_,
                  user0_.version as version2_1_0_,
                  user0_.name as name3_1_0_,
                  user0_.age as age4_1_0_ 
              from
                  t_user user0_ 
              where
                  user0_.id=?
          小風
          Hibernate: 
              update
                  t_user 
              set
                  version=?,
                  name=?,
                  age=? 
              where
                  id=? 
                  and version=?
        
      • 從中可以發(fā)現(xiàn),在測試代碼中我們把 session.update(user); 注釋掉了扰法,但是在控制臺中發(fā)現(xiàn)仍有 update 語句蛹含,這就是持久態(tài)有自動更新數(shù)據(jù)庫的能力,具體原因是 Session 對象的一級緩存(見下節(jié))塞颁。

  1. 三個狀態(tài)之間的轉(zhuǎn)換圖解:

3浦箱、Hibernate 的一級緩存

  • Session 對象的一級緩存

    1. 什么是緩存?

      • 其實就是一塊內(nèi)存空間祠锣,將數(shù)據(jù)源(數(shù)據(jù)庫或者文件)中的數(shù)據(jù)存放到緩存中酷窥。再次獲取的時候,直接從緩存中獲取伴网,可以提升程序的性能蓬推!
    2. Hibernate 框架提供了兩種緩存

      • 一級緩存 -- 自帶的不可卸載的。一級緩存的生命周期與 session 一致澡腾,一級緩存稱為 session 級別的緩存.
      • 二級緩存 -- 默認沒有開啟沸伏,需要手動配置才可以使用的。二級緩存可以在多個 session 中共享數(shù)據(jù),二級緩存稱為是 sessionFactory 級別的緩存.
    3. Session 對象的緩存概述

      • Session 接口中动分,有一系列的 java 的集合,這些 java 集合構(gòu)成了 Session 級別的緩存(一級緩存)毅糟。將對象存入到一級緩存中,session 沒有結(jié)束生命周期,那么對象在 session 中存放著。
      • 內(nèi)存中包含 Session 實例 --> Session 的緩存(一些集合) --> 集合中包含的是緩存對象澜公!
    4. 證明一級緩存的存在姆另,編寫查詢的代碼即可證明

      • 在同一個 Session 對象中兩次查詢,可以證明使用了緩存玛瘸。
      • 測試代碼:

          @Test
          public void run3(){
              Session session = HibernateUtils.getSession();
              Transaction tr = session.beginTransaction();
              
              // 最簡單的證明蜕青,查詢兩次
              User user1 = session.get(User.class, 1);
              System.out.println(user1.getName());
              
              User user2 = session.get(User.class, 1);
              System.out.println(user2.getName());
              
              tr.commit();
              session.close();
          }
        
      • 控制臺只輸出一次如下信息:

          Hibernate: 
              insert 
              into
                  t_user
                  (version, name, age) 
              values
                  (?, ?, ?)
        
      • 進一步分析,若采用斷點的方式 debug糊渊,發(fā)現(xiàn)在執(zhí)行 User user2 = session.get(User.class, 1); 時右核,控制臺不輸出任何信息,所以證明了一級緩存的存在渺绒。

    5. Hibernate 框架是如何做到數(shù)據(jù)發(fā)生變化時進行同步操作的呢贺喝?

      • 實驗步驟: 使用 get 方法查詢 User 對象菱鸥,然后設(shè)置 User 對象的一個屬性,注意:沒有做 update 操作躏鱼。最后發(fā)現(xiàn)氮采,數(shù)據(jù)庫中的記錄也改變了。
      • 原因:利用快照機制來完成的(SnapShot)染苛,且該特性正好和持久態(tài)擁有自動更新數(shù)據(jù)庫能力相符合鹊漠。
      • 快照機制:


  • 控制 Session 的一級緩存(了解)

    • 學習Session接口中與一級緩存相關(guān)的方法
      • Session.clear() -- 清空緩存。

        • 測試代碼:

            /**
             * Session.clear()  -- 清空緩存茶行。
             */
            @Test
            public void run5(){
                Session session = HibernateUtils.getSession();
                Transaction tr = session.beginTransaction();
                
                // 最簡單的證明躯概,查詢兩次
                User user1 = session.get(User.class, 1);
                System.out.println(user1.getName());
                
                // 清空緩存
                session.clear();
                
                User user2 = session.get(User.class, 1);
                System.out.println(user2.getName());
                
                tr.commit();
                session.close();
            }
          
        • 控制臺輸出:

            Hibernate: 
                select
                    user0_.id as id1_1_0_,
                    user0_.version as version2_1_0_,
                    user0_.name as name3_1_0_,
                    user0_.age as age4_1_0_ 
                from
                    t_user user0_ 
                where
                    user0_.id=?
            隔離老王
            Hibernate: 
                select
                    user0_.id as id1_1_0_,
                    user0_.version as version2_1_0_,
                    user0_.name as name3_1_0_,
                    user0_.age as age4_1_0_ 
                from
                    t_user user0_ 
                where
                    user0_.id=?
            隔離老王
          
        • 由此可見,clear方法可以清除緩存畔师。

      • Session.evict(Object entity) -- 從一級緩存中清除指定的實體對象娶靡。

        • 若把上面代碼中的 session.clear(); 改為 session.evict(user1);,則控制臺輸出仍如上看锉。
      • Session.flush() -- 刷出緩存

        • 在一般的快照機制中姿锭,是在事務(wù)提交時(tr.commit();)伯铣,比較緩存與快照的不同呻此,然后 Hibernate 框架自動執(zhí)行 update SQL 語句,再更新數(shù)據(jù)庫腔寡。

        • 而如果調(diào)用 flush 方法趾诗,則在執(zhí)行該方法時就比較緩存與快照的不同,然后 Hibernate 框架自動執(zhí)行 update SQL 語句蹬蚁,最后在事務(wù)提交時更新數(shù)據(jù)庫恃泪。

        上面兩點的區(qū)別本人經(jīng)過斷點調(diào)試一一驗證,以保證其正確性犀斋。

4贝乎、Hibernate 中的事務(wù)與并發(fā)

  • 事務(wù)相關(guān)的概念

    1. 什么是事務(wù)

      • 事務(wù)就是邏輯上的一組操作,組成事務(wù)的各個執(zhí)行單元叽粹,操作要么全都成功览效,要么全都失敗.
      • 轉(zhuǎn)賬的例子:冠希給美美轉(zhuǎn)錢,扣錢虫几,加錢锤灿。兩個操作組成了一個事情!
    2. 事務(wù)的特性

      • 原子性 -- 事務(wù)不可分割.
      • 一致性 -- 事務(wù)執(zhí)行的前后數(shù)據(jù)的完整性保持一致.
      • 隔離性 -- 一個事務(wù)執(zhí)行的過程中,不應(yīng)該受到其他的事務(wù)的干擾.
      • 持久性 -- 事務(wù)一旦提交,數(shù)據(jù)就永久保持到數(shù)據(jù)庫中.
    3. 如果不考慮隔離性:引發(fā)一些讀的問題

      • 臟讀 -- 一個事務(wù)讀到了另一個事務(wù)未提交的數(shù)據(jù)(數(shù)據(jù)庫隔離中最重要的問題)
      • 不可重復(fù)讀 -- 一個事務(wù)讀到了另一個事務(wù)已經(jīng)提交的 update 數(shù)據(jù),導(dǎo)致多次查詢結(jié)果不一致.
      • 虛讀 -- 一個事務(wù)讀到了另一個事務(wù)已經(jīng)提交的 insert 數(shù)據(jù),導(dǎo)致多次查詢結(jié)構(gòu)不一致.
    4. 通過設(shè)置數(shù)據(jù)庫的隔離級別來解決上述讀的問題

      • 未提交讀:以上的讀的問題都有可能發(fā)生.
      • 已提交讀:避免臟讀,但是不可重復(fù)讀辆脸,虛讀都有可能發(fā)生.
      • 可重復(fù)讀:避免臟讀但校,不可重復(fù)讀.但是虛讀是有可能發(fā)生.
      • 串行化:以上讀的情況都可以避免.
    5. 如果想在Hibernate的框架中來設(shè)置隔離級別,需要在 hibernate.cfg.xml 的配置文件中通過標簽來配置

      • 通過:hibernate.connection.isolation = 4 來配置
      • 取值:
        • 1—Read uncommitted isolation
        • 2—Read committed isolation
        • 4—Repeatable read isolation
        • 8—Serializable isolation
  • 丟失更新的問題

    1. 如果不考慮隔離性啡氢,也會產(chǎn)生寫入數(shù)據(jù)的問題状囱,這一類的問題叫丟失更新的問題术裸。

    2. 例如:兩個事務(wù)同時對某一條記錄做修改,就會引發(fā)丟失更新的問題亭枷。

      • A 事務(wù)和 B 事務(wù)同時獲取到一條數(shù)據(jù)袭艺,同時再做修改
      • 如果 A 事務(wù)修改完成后,提交了事務(wù)
      • B 事務(wù)修改完成后叨粘,不管是提交還是回滾猾编,如果不做處理,都會對數(shù)據(jù)產(chǎn)生影響


    3. 解決方案有兩種

      • 悲觀鎖

        • 采用的是數(shù)據(jù)庫提供的一種鎖機制升敲,如果采用做了這種機制袍镀,在SQL語句的后面添加 for update 子句

          • 當A事務(wù)在操作該條記錄時,會把該條記錄鎖起來冻晤,其他事務(wù)是不能操作這條記錄的。

          • 只有當A事務(wù)提交后绸吸,鎖釋放了鼻弧,其他事務(wù)才能操作該條記錄

      • 樂觀鎖

        • 使用的不是數(shù)據(jù)庫鎖機制,而是采用版本號的機制來解決的锦茁。給表結(jié)構(gòu)添加一個字段 version=0攘轩,默認值是0

          • 當 A 事務(wù)在操作完該條記錄,提交事務(wù)時码俩,會先檢查版本號度帮,如果發(fā)生版本號的值相同時,才可以提交事務(wù)稿存。同時會更新版本號 version=1.

          • 當 B 事務(wù)操作完該條記錄時笨篷,提交事務(wù)時,會先檢查版本號瓣履,如果發(fā)現(xiàn)版本不同時率翅,程序會出現(xiàn)錯誤。

    4. 使用 Hibernate 框架解決丟失更新的問題

      • 悲觀鎖(效率較低袖迎,不常見)

        • 使用 session.get(Customer.class, 1,LockMode.UPGRADE); 方法
      • 樂觀鎖

        • 在對應(yīng)的 JavaBean 中添加一個屬性冕臭,名稱可以是任意的。例如:private Integer version; 提供 get 和 set 方法

        • 在映射的配置文件中燕锥,提供<version name="version"/>標簽即可辜贵。

    附上本人以前學習的筆記,從 JDBC 角度分析事務(wù)归形、隔離級別托慨、丟失更新問題:http://www.reibang.com/p/aacde54542b5

  • 綁定本地的 Session

    1. 在上文所附的文章里,講解了 JavaWEB 的事務(wù)暇榴,需要在業(yè)務(wù)層使用 Connection 來開啟事務(wù)榴芳。

      • 一種是通過參數(shù)的方式嗡靡,一層一層的傳遞下去
      • 另一種是把 Connection 綁定到 ThreadLocal 對象中,因為 ThreadLocal 對于內(nèi)通過 map 存儲了 key = 當前線程, value= Connection對象

      ThreadLocal 兩個重要方法

      • get
        public T get() 返回此線程局部變量的當前線程副本中的值窟感。如果變量沒有用于當前線程的值讨彼,則先將其初始化為調(diào)用 initialValue() 方法返回的值。
        返回:
        此線程局部變量的當前線程的值
      • set
        public void set(T value) 將此線程局部變量的當前線程副本中的值設(shè)置為指定值柿祈。大部分子類不需要重寫此方法哈误,它們只依靠 initialValue() 方法來設(shè)置線程局部變量的值。
        參數(shù):
        value - 存儲在此線程局部變量的當前線程副本中的值躏嚎。
    2. 在 Hibernate 框架中蜜自,使用 session 對象開啟事務(wù),而 session 對象存在于業(yè)務(wù)層中卢佣,所以需要把 session 對象傳遞到持久層重荠,在持久層使用 session 對象操作數(shù)數(shù)據(jù)對象,框架提供了 ThreadLocal 的方式:

      • 首先需要在 hibernate.cfg.xml 的配置文件中提供配置

          <property name="hibernate.current_session_context_class">thread</property>
        
      • 然后重寫 HibernateUtil 的工具類虚茶,使用 SessionFactory 的 getCurrentSession( )方法戈鲁,獲取當前的 Session 對象。并且該 Session 對象不用手動關(guān)閉嘹叫,線程結(jié)束了婆殿,會自動關(guān)閉。

        • HibernateUtil 工具類:

            package com.itheima.utils;
            
            import org.hibernate.Session;
            import org.hibernate.SessionFactory;
            import org.hibernate.cfg.Configuration;
            
            /**
             * Hibernate框架的工具類
             * @author Administrator
             */
            public class HibernateUtils {
                
                // ctrl + shift + x
                private static final Configuration CONFIG;
                private static final SessionFactory FACTORY;
                
                // 編寫靜態(tài)代碼塊
                static{
                    // 加載XML的配置文件
                    CONFIG = new Configuration().configure();
                    // 構(gòu)造工廠
                    FACTORY = CONFIG.buildSessionFactory();
                }
                
                /**
                 * 從工廠中獲取Session對象
                 * @return
                 */
                public static Session getSession(){
                    return FACTORY.openSession();
                }
                
                /**
                 * // 從ThreadLocal類中獲取到session的對象
                 * @return
                 */
                public static Session getCurrentSession(){
                    return FACTORY.getCurrentSession();
                }
                
            }
          
        • UserService 業(yè)務(wù)層:

            package com.itheima.service;
            
            import org.hibernate.Session;
            import org.hibernate.Transaction;
            
            import com.itheima.dao.UserDao;
            import com.itheima.domain.User;
            import com.itheima.utils.HibernateUtils;
            
            public class UserService {
                
                public void save(User u1,User u2){
                    UserDao dao = new UserDao();
                    // 獲取session
                    Session session = HibernateUtils.getCurrentSession();
                    // 開啟事務(wù)
                    Transaction tr = session.beginTransaction();
                    try {
                        dao.save1(u1);
                        int a = 10/0;
                        dao.save2(u2);
                        // 提交事務(wù)
                        tr.commit();
                    } catch (Exception e) {
                        e.printStackTrace();
                        // 出現(xiàn)問題:回滾事務(wù)
                        tr.rollback();
                    }finally{
                        // 自己釋放資源罩扇,現(xiàn)在婆芦,session不用關(guān)閉,線程結(jié)束了喂饥,自動關(guān)閉的O肌!
                    }
                }
            }
          
        • UserDao 持久層:

            package com.itheima.dao;
            
            import org.hibernate.Session;
            
            import com.itheima.domain.User;
            import com.itheima.utils.HibernateUtils;
            
            public class UserDao {
                
                public void save1(User u1){
                    Session session = HibernateUtils.getCurrentSession();
                    session.save(u1);
                    //不用寫 session.close; 
                }
                
                public void save2(User u2){
                    Session session = HibernateUtils.getCurrentSession();
                    session.save(u2);
                }
            
            }
          
      • 注意:想使用 getCurrentSession() 方法员帮,必須要先配置才能使用荆陆。

5、Hibernate 的查詢方式(HQL:Hibernate Query Language)

  • Query 查詢接口

    • 具體的查詢代碼如下:

        // 1.查詢所有記錄
        /*Query query = session.createQuery("from Customer");
        List<Customer> list = query.list();
        System.out.println(list);*/
        
        // 2.條件查詢(? 從0開始)
        /*Query query = session.createQuery("from Customer where name = ?");
        query.setString(0, "李健");
        List<Customer> list = query.list();
        System.out.println(list);*/
        
        // 3.條件查詢(設(shè)置別名)
        /*Query query = session.createQuery("from Customer where name = :aaa and age = :bbb");
        query.setString("aaa", "李健");
        query.setInteger("bbb", 38);
        List<Customer> list = query.list();
        System.out.println(list);*/
      
        // 4.模糊查詢(注意 % 要寫在 setString 里面)
        /*Query query = session.createQuery("from User where name like ?");
        query.setString(0, "%老%");
        List<Customer> list = query.list();
        System.out.println(list);*/
      

      在 JDBC 中集侯,記錄從1開始被啼!
      在 HQL 中,記錄從0開始棠枉!

  • Criteria 查詢接口(做條件查詢非常合適)

    • 完全面向?qū)ο笈ㄌ澹a中基本不會體現(xiàn) SQL 語言的特點

    • Criterion 是 Hibernate 提供的條件查詢的對象,如果想傳入條件辈讶,可以使用工具類 Restrictions 命浴,在其內(nèi)部有許多靜態(tài)方法可以用來描述條件

    • 具體的查詢代碼如下

        // 1.查詢所有記錄
        /*Criteria criteria = session.createCriteria(Customer.class);
        List<Customer> list = criteria.list();
        System.out.println(list);*/
        
        // 2.條件查詢(查詢 name 字段為李健的記錄)
        /*Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.eq("name", "李健"));
        List<Customer> list = criteria.list();
        System.out.println(list);*/
        
        // 3.條件查詢(查詢 name 字段為李健、age 字段為38的記錄)
        /*Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.eq("name", "李健"));
        criteria.add(Restrictions.eq("age", 38));
        List<Customer> list = criteria.list();
        System.out.println(list);*/
      
        // Restrictions 提供了許多靜態(tài)方法來描述條件
        criteria.add(Restrictions.gt("age", 18)); // gt:大于
        criteria.add(Restrictions.like("name", "%小%")); // like:模糊查詢
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市生闲,隨后出現(xiàn)的幾起案子媳溺,更是在濱河造成了極大的恐慌,老刑警劉巖碍讯,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悬蔽,死亡現(xiàn)場離奇詭異,居然都是意外死亡捉兴,警方通過查閱死者的電腦和手機蝎困,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倍啥,“玉大人禾乘,你說我怎么就攤上這事∷渎疲” “怎么了始藕?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長氮趋。 經(jīng)常有香客問我伍派,道長,這世上最難降的妖魔是什么凭峡? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮决记,結(jié)果婚禮上摧冀,老公的妹妹穿的比我還像新娘。我一直安慰自己系宫,他們只是感情好索昂,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扩借,像睡著了一般椒惨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上潮罪,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天康谆,我揣著相機與錄音,去河邊找鬼嫉到。 笑死沃暗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的何恶。 我是一名探鬼主播孽锥,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惜辑?” 一聲冷哼從身側(cè)響起唬涧,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盛撑,沒想到半個月后碎节,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡撵彻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年钓株,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陌僵。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡轴合,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碗短,到底是詐尸還是另有隱情受葛,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布偎谁,位于F島的核電站总滩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏巡雨。R本人自食惡果不足惜闰渔,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铐望。 院中可真熱鬧冈涧,春花似錦、人聲如沸正蛙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乒验。三九已至愚隧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锻全,已是汗流浹背狂塘。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鳄厌,地道東北人睹耐。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像部翘,于是被迫代替她去往敵國和親硝训。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容