激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Hibernate hql查詢代碼實例

Hibernate hql查詢代碼實例

2021-04-02 15:40lavimer Java教程

這篇文章主要介紹了Hibernate hql查詢代碼實例,分享了相關代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是Hibernate hql查詢的相關內容,具體如下。

 

HQL介紹

Hibernate語言查詢(Hibernate Query Language,HQL)它是完全面向對象的查詢語句,查詢功能非常強大;具備多態、關聯等特性,HQL查詢也是Hibernate官方推薦使用的查詢方法。

下面我們通過一個案例我分析相關查詢方法

Classes.java:

?
1
2
3
4
5
6
7
8
9
public class Classes {
    /*班級ID*/
    private int id;
    /*班級名稱*/
    private String name;
    /*班級和學生的關系*/
    private Set<Student> students;
    //省略setter和getter方法
}

Student.java:

?
1
2
3
4
5
6
7
8
9
public class Student {
    /*學生ID*/
    private int id;
    /*學生姓名*/
    private String name;
    /*學生和班級的關系*/
    private Classes classes;
    //省略setter和getter方法
}

Classes.hbm.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
  <!-- 設置lazy為false -->
  <class name="Classes" table="t_classes" lazy="false">
    <id name="id">
      <generator class="native"/>
    </id>
    <property name="name"/>
    <!-- 一對多映射 ,inverse="true"表示交給對端維護關系-->
    <set name="students" inverse="true">
       <key column="classesid"/>
      <one-to-many class="Student"/>
    </set>
  </class>
</hibernate-mapping>

Student.hbm.xml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.lixue.bean">
  <class name="Student" table="t_student">
    <id name="id">
      <generator class="native"/>
    </id>
    <!-- 映射普通屬性 -->
    <property name="name"/>
    <!-- 多對一 映射,在多的一端加上外鍵-->
    <many-to-one name="classes" column="classesid"/>
  </class>
</hibernate-mapping>

 

1.查詢單一屬性:

?
1
2
3
4
5
6
7
/*返回結果集屬性列表,元素類型和實體類中的屬性類型一致*/
      List<String> students = session.createQuery("select name from Student").list();
      /*遍歷*/
      for (Iterator<String> iter=students.iterator(); iter.hasNext();) {
        String name = (String)iter.next();
        System.out.println(name);
      }

注:查詢單一屬性的時候,返回的是一個集合,集合元素的類型是該屬性的類型。

 

2.查詢多個屬性,返回對象數組:

?
1
2
3
4
5
6
7
/*查詢多個屬性,返回的是對象數組*/
      List<Object[]> students = session.createQuery("select id, name from Student").list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:查詢多個屬性返回的是一個類型為對象數組的集合,這個很好理解,當查詢單一屬性是返回的集合元素類型就是屬性的類型,但是多個類型呢?那必須是對象數組來處理啊即Object[]。

 

3.查詢多個屬性,返回對象類型的集合:

?
1
2
3
4
5
6
7
/*我們給實體對象設置對應的構造函數,然后通過查詢對象的方式就可以返回一個實體對象類型的集合*/
      List students = session.createQuery("select new Student(id, name) from Student").list();
      /*遍歷*/
      for (Iterator iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getId() + ", " + student.getName());
      }

注:除了我們第二種方式返回的是一個對象數組,我們還可以給實體對象設置對應的構造函數,然后通過查詢對象的方式進行查詢,然后返回的就是實體類型的集合。

 

4.使用別名進行查詢:

?
1
2
3
4
5
6
7
/*可以使用別名*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s").list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

 

5.查詢實體對象:

?
1
2
3
4
5
6
7
/*返回的是實體對象類型的集合*/
      List<Student> students = session.createQuery("from Student").list();
      /*遍歷*/
      for (Iterator<Student> iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:查詢實體可以直接使用from 類名的形式。

?
1
2
3
4
5
6
7
/*使用select就必須使用別名*/
      List<Student> students = session.createQuery("select s from Student s").list();
      /*遍歷*/
      for (Iterator<Student> iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:如果要使用select關鍵字,那么就必須使用別名。另外一點千萬要注意:hql不支select * 的形式。

 

6.N+1問題:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
       * 采用list查詢實體對象會發出一條查詢語句,取得實體對象數據
       *
       * Hibernate: select student0_.id as id0_, student0_.name as name0_,
       * student0_.createTime as createTime0_, student0_.classesid as classesid0_
       * from t_student student0_
       */
      List<Student> students = session.createQuery("from Student").list();
      /*遍歷*/
      for (Iterator<Student> iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:使用.list()的方式進行對象查詢,只會發出一條語句,即取得實體對象數據的語句。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
       * 會出現N+1問題,所謂的N+1指的是發出了N+1條sql語句
       *
       * 1:發出一條查詢id列表的語句
       * Hibernate: select student0_.id as col_0_0_ from t_student student0_
       *
       * N:根據id發出N條sql語句,加載相關的對象
       * Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_,
       * student0_.createTime as createTime0_0_, student0_.classesid as classesid0_0_
       * from t_student student0_ where student0_.id=?
       *
       */
      Iterator<Student> iter = session.createQuery("from Student").iterate();
      /*遍歷*/
      while (iter.hasNext()) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:通過iterator()方式進行對象查詢,會發出N+1條語句,首先會發出一條語句查詢出實體對象的ID,然后在根據各自的ID發出N條語句去查詢N個對象,這中形式性能是比較差的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*通過List查詢把查詢出的集合存放在一級緩存即session級緩存中*/
      List<Student> students = session.createQuery("from Student").list();
      /*遍歷*/
      for (Iterator<Student> iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }
      System.out.println("-----------------------------------------------------");
      /**
       * 避免了N+1問題
       *
       * 因為執行list操作后會將數據放到session的緩存中(一級緩存),所以采用iterate的時候
       * 首先會發出一條查詢id列表的語句,再根據id到緩存中加載相應的數據,如果緩存中存在與之匹配的數據
       * 則不再發出根據id查詢的sql語句,直接使用緩存中的數據
       *
       * Iterate方法如果緩存中存在數據,它可以提高性能,否則出現N+1問題
       *
       */
      Iterator<Student> iter = session.createQuery("from Student").iterate();
      /*遍歷*/
      while (iter.hasNext()) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:其實Hibernate提供iterator()的方式查詢是為了提高性能的,那為什么反而幫了倒忙呢?原因是iterator()是從一級緩存中取數據的,如果緩存中有數據,那么它的效率毫無疑問會相當的給力,但是當我第一次查詢的時候緩存中怎么可能會有數據呢,所以就導致了所謂的N+1問題。上面這段代碼可以避免N+1問題,它的思路是先用list()進行查詢,因為list()查詢出來以后,在一級緩存匯總就存在了數據,使用iterator()的時候,效率就會非常的高。

 

7.條件查詢:

?
1
2
3
4
5
6
7
/*根據條件進行查詢(這里通常都使用別名,比較方便 )*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where s.name like '%0%'").list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:條件查詢和原生的sql相同,都是where關鍵字。另外通常使用別名比較方便,上述程序是查詢多個屬性,所以返回的是對象數組類型的集合,對象數組中的元素就是對應的屬性。

 

8.占位符的形式查詢:

?
1
2
3
4
5
6
7
8
9
/*鏈式編程*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
          .setParameter(0, "%0%")
          .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:可以通過占位符的形式進行傳參,這種方式可以防止SQL注入。

 

9.自定義參數的形式:

?
1
2
3
4
5
6
7
8
9
/*鏈式編程*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
          .setParameter("myname", "%0%")
          .list();
      /*對象數組*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:like :myname冒號后面是沒有空格的,否則會出錯。

 

10.查詢條件為in的形式:

?
1
2
3
4
5
6
7
8
9
10
[java] view plain copy
/*采用in的方式,形參只要一個即可*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where s.id in(:ids)")
          .setParameterList("ids", new Object[]{1, 2, 3, 4, 5})
          .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:in后面的括號中只要有一個形參即可,我們設置參數值的時候,可以通過對象數組就行傳值。

 

11.使用數據庫個性化函數:

?
1
2
3
4
5
6
7
8
9
/*查詢2009-08的學生,可以調用mysql的日期格式化函數*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where date_format(s.createTime, '%Y-%m')=?")
          .setParameter(0, "2009-08")
          .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }
?
1
2
3
4
5
6
7
8
9
10
11
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      /*查詢2009-08-01 到2009-08-20的學生,可以調用mysql的日期格式化函數*/
      List<Object[]> students = session.createQuery("select s.id, s.name from Student s where s.createTime between ? and ?")
          .setParameter(0, sdf.parse("2009-08-01 00:00:00"))
          .setParameter(1, sdf.parse("2009-08-20 23:59:59"))
          .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

 

12.使用原生態的SQL語句:

?
1
2
3
4
5
6
7
/*使用select * 必須使用原生態的SQL語句,另外它類似于hql查詢多個屬性,所以返回的是一個對象數組類型的集合*/
      List<Object[]> students = session.createSQLQuery("select * from t_student").list();
      /*遍歷*/
      for (Iterator<Object[]> iter = students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[]) iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:hql不支持select * 的查詢形式,但是Hibernate支持原生態的SQL語句,我們可以利用SQL語句進行查詢,另外它類似于HQL的查詢多個屬性,所以返回的是一個對象數組類型的集合。

 

13.分頁查詢

?
1
2
3
4
5
6
7
8
9
10
/*分頁查詢,setFirstResult(1)表示從第一條數據開始查詢;setMaxResult(2)表示每頁顯示2條數據*/
      List students = session.createQuery("from Student")
            .setFirstResult(1)
            .setMaxResults(2)
            .list();
      /*遍歷*/
      for (Iterator iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

 

14.導航查詢

?
1
2
3
4
5
6
7
8
/*導航查詢,s.classes.name從學生導航到班級在導航到班級名稱(這是從多的一端導航到少的一端,反過來也可以)*/
      List<Student> students = session.createQuery("from Student s where s.classes.name like '%2%'")
            .list();
      /*遍歷*/
      for (Iterator<Student> iter=students.iterator(); iter.hasNext();) {
        Student student = (Student)iter.next();
        System.out.println(student.getName());
      }

注:上述查詢語句中的s.classes.name是從學生導航到班級classes在獲取班級的名稱name。也可以反過來導航:從班級導航到學生在得到某個屬性。另外程序中查詢語句的意思是要查詢班級名稱中含有2的所有學生。

 

15.內連接查詢

?
1
2
3
4
5
6
7
8
/*內連接,使用join關鍵字即可*/
    List<Object[]> students = session.createQuery("select c.name, s.name from Student s join s.classes c")
          .list();
    /*遍歷*/
    for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
      Object[] obj = (Object[])iter.next();
      System.out.println(obj[0] + ", " + obj[1]);
    }

注:內連接關鍵字為join,另外還是用了別名和導航進行連接。上述查詢語句的意思為:從學生表和班級表中查詢中班級名稱和學生名稱(內連接是查詢出必須有值得屬性,比如沒有班級沒有學生或者學生沒有班級是查詢不出來的)。

 

16.左連接

?
1
2
3
4
5
6
7
8
/*左連接使用關鍵字left join*/
      List<Object[]> students = session.createQuery("select c.name, s.name from Student s left join s.classes c")
            .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:使用左連接的關鍵字為left join。上述查詢語句的意思為:從學生和班級表中,查詢出班級名稱和學生名稱,因為是左連接,所以沒有班級的學生也會被查詢出來。

 

17.右連接

?
1
2
3
4
5
6
7
8
9
[java] view plain copy
/*右連接關鍵字為right join*/
      List<Object[]> students = session.createQuery("select c.name, s.name from Student s right join s.classes c")
            .list();
      /*遍歷*/
      for (Iterator<Object[]> iter=students.iterator(); iter.hasNext();) {
        Object[] obj = (Object[])iter.next();
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:使用右連接的關鍵字為right join。上述查詢語句的意思為:從學生和班級表中,查詢出班級名稱和學生名稱,因為是右連接,所以沒有學生的班級會被查詢出來。

 

18.統計查詢

?
1
Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();

注:hql中唯有統計查詢才可以帶*號。uniqueResult()表示只有一條結果集,返回的是Long類型。

 

19.復合查詢

?
1
2
3
4
5
6
7
8
9
/*查詢語句*/
      String hql = "select c.name, count(s) from Classes c join c.students s group by c.name order by c.name";
       
      List<Object[]> students = session.createQuery(hql).list();
      /*遍歷*/
      for (int i=0; i<students.size(); i++) {
        Object[] obj = (Object[])students.get(i);
        System.out.println(obj[0] + ", " + obj[1]);
      }

注:hql同樣支持分組、排序等等。上述語句的意思是:查詢每個班級的名稱并且查詢出每個班級的學生人數,按班級名稱分組,按班級名稱排序

 

總結

以上就是本文關于Hibernate hql查詢代碼實例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://blog.csdn.net/lzm1340458776/article/details/33769937

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国内一区 | 一级美女大片 | 久久免费视频3 | 毛片视频大全 | 欧美曾交| 麻豆小视频在线观看 | 欧美一级aa免费毛片 | 亚洲爱爱网站 | 亚洲综合一区在线观看 | 免费国产精品视频 | 久久99久久99免费视频 | a视频网站 | 国产免费一区二区三区 | 国产女厕一区二区三区在线视 | www.777含羞草 | 成人羞羞视频在线观看 | 欧美一级免费在线观看 | 涩涩伊人 | 亚洲国产精品久久久久制服红楼梦 | 久久成人激情视频 | 久久96国产精品久久久 | sese在线视频 | 毛片在线播放视频 | 91中文在线| 亚洲精品午夜电影 | av在线免费看网站 | 蜜桃网站在线 | 黄在线观看 | 有色视频在线观看 | 成年片在线观看 | 媚药按摩痉挛w中文字幕 | 午夜精品小视频 | 黄污视频在线看 | 成人超碰97 | 91亚洲精品一区二区福利 | 黄色免费大片 | 国产精品欧美久久久久一区二区 | 涩涩伊人 | 久久成人视屏 | 久久草草影视免费网 | 超91在线|