天天看點

第八篇 Hibernate之9種查詢方式

Hibernate總的來說共有四種查詢方式:HQL、QBC、QBE和SQL四種。但是細分可以有如下幾種:

一、HQL查詢方式

    這一種我最常用,也是最喜歡用的,因為它寫起來靈活直覺,而且與所熟悉的SQL的文法差不太多。條件查詢、分頁查詢、連接配接查詢、嵌套查詢,寫起來與SQL文法基本一緻,唯一不同的就是把表名換成了類或者對象。其它的,包括一些查詢函數(count(),sum()等)、查詢條件的設定等,全都跟SQL文法一樣。在這裡需要提醒一下的是: 在hql中關鍵字不區分大小寫,但是屬性和類名區分大小寫

示例1:

  static void query(String name){

  Session s=null;

  try{

   s=HibernateUtil.getSession();

   //from後面是對象,不是表名

   String hql="from Admin as admin where admin.aname=:name";//使用命名參數,推薦使用,易讀。

   Query query=s.createQuery(hql);

   query.setString("name", name);

   List<Admin> list=query.list();

   for(Admin admin:list){

       System.out.println(admin.getAname());

   }

  }finally{

   if(s!=null)    s.close();

 }

}

######!!!!!!!!!!!!!對于多對一關系查詢:

  String hql = "from Student whereClass.className = '微機76班'";

(Student實體類中含有Class對象的引用。這樣相當于兩張表的聯合查詢)

示例2(分頁查詢):

Query query = session.createQuery("from Customer c

order by c.name asc");

query.setFirstResult(0);

query.setMaxResults(10);

List result = query.list();

    說明:

   –setFirstResult(int firstResult):設定從哪一個對象開始檢索,參數firstResult表示這個對象在查詢結果中的索引位置,索引位置的起始值為0。預設情況下,Query和Criteria接口從查詢結果中的第一個對象,也就是索引位置為0的對象開始檢索。 

    –setMaxResult(int maxResults):設定一次最多檢索出的對象數目。預設情況下,Query和Criteria接口檢索出查詢結果中所有的對象。

适用情況:常用方法,比較傳統,類似jdbc。缺點:新的查詢語言,适用面有限,僅适用于Hibernate架構。

二、QBC(Query By Criteria) 查詢方式

   這種方式比較面向對象方式,重點是有三個描述條件的對象:Restrictions,Order,Projections。使用QBC查詢,一般需要以下三個步驟:

   1、 使用Session執行個體的createCriteria()方法建立Criteria對象

   2、使用工具類Restrictions的方法為Criteria對象設定查詢條件,Order工具類的方法設定排序方式,Projections工具類的方法進行統計和分組。

   3、使用Criteria對象的list()方法進行查詢并傳回結果

Restrictions類的常用方法:

Restrictions類的常用方法:

方法名稱
描述
Restrictions.eq 等于
Restrictions.allEq 使用Map,Key/Valu進行多個等于的比對
Restrictions.gt 大于
Restrictions.ge 大于等于
Restrictions.lt 小于
Restrictions.le 小于等于
Restrictions.between 對應SQL的between
Restrictions.like 對應SQL的like
Restrictions.in 對應SQL的in
Restrictions.and and關系
Restrictions.or or關系
Restrictions.sqlRestriction SQL限定查詢

Order類的常用方法:

方法名稱
描述
Order.asc 升序
Order.desc 降序

Projections類的常用方法

方法名稱
描述
Projections.avg 求平均值
Projections.count 統計某屬性的數量
Projections.countDistinct 統計某屬性不同值的數量
Projections.groupProperty 指定某個屬性為分組屬性
Projections.max 求最大值
Projections.min 求最小值
Projections.projectionList 建立一個ProjectionList對象
Projections.rowCount 查詢結果集中的記錄條數
Projections.sum 求某屬性的合計

示例:static void cri(String name,String password){

  Session s=null;

  try{

   s=HibernateUtil.getSession();

   Criteria c=s.createCriteria(Admin.class);

   c.add(Restrictions.eq("aname",name));//eq是等于,gt是大于,lt是小于,or是或

   c.add(Restrictions.eq("apassword", password));

   List<Admin> list=c.list();

   for(Admin admin:list){

     System.out.println(admin.getAname());

   }

  }finally{

     if(s!=null)   s.close();

  }

}

示例2(分頁查詢):

Criteria criteria = session.createCriteria(Customer.class);

criteria.addOrder( Order.asc("name") ); //排序方式

criteria.setFirstResult(0);

criteria.setMaxResults(10);

List result = criteria.list()

  适用情況:面向對象操作,革新了以前的資料庫操作方式,易讀。缺點:适用面較HQL有限。

三、QBE(Query By Example)例子查詢方式

   将一個對象的非空屬性作為查詢條件進行查詢。

 示例:Session session = SessionFactory.getCurrentSession();

   User user = new User();

   user.setName("ijse");

   Transaction ts = session.beginTransaction();

    try {

        Criteria criteria = session.createCriteria(User.class);

        criteria.add(Example.create(user));

        user= (User) criteria.list().get(0);   

        session.commit();

   } catch (HibernateException ex) {

       ts.rollBack();

       ex.printStackTrace();

   }

   System.out.println(user.getName());

适用情況:面向對象操作。   缺點:适用面較HQL有限,不推薦。

四、DetachedCriteria:離線條件查詢

   離線查詢就是建立一個DetachedCriteria對象,将查詢的條件等指定好,然後在session.beginTransaction()後将這個對象傳入。通常這個對象可以在表示層建立,然後傳入業務層進行查詢。

  1、建立DetachedCriteria對象

    DetachedCriteria dc = DetachedCriteria.forClass(User.class);

   int id = 1;

   if (id != 0)

   dc.add(Restrictions.eq("id", id));

   Date age = new Date();

   if (age != null)

   dc.add(Restrictions.le("birthday", age));

   List users = dc(dc);//執行查詢

   System.out.println("離線查詢傳回結果:" + users);

 2、執行查詢

   static List dc(DetachedCriteria dc) {

       Session s = HibernateUtil.getSession();

       Criteria c = dc.getExecutableCriteria(s);

       List rs = c.list();

       s.close();

       return rs;

   }

适用情況:面向對象操作,分離業務與底層,不需要字段屬性攝入到Dao實作層。  缺點:适用面較HQL有限。

五、命名查詢

  1、在資料映射元檔案中進行配置如下:

 <?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="com.sy.vo.User" table="user" catalog="news">

   ....

    </class>

    <!-- 命名查詢:定義查詢條件 -->

    <query name="getUserById">

     <![CDATA[from User where id=:id]]>

    </query>

    <!-- 命名查詢中使用sql,不推薦使用,影響跨資料庫

    <sql-query name="getUserById2">

     <![CDATA[select * from User where ]]>

    </sql-query> -->

</hibernate-mapping>

  2、在java代碼中寫入:

  static List namedQuery(int id) {

  Session s = HibernateUtil.getSession();

  Query q = s.getNamedQuery("getUserById");

  q.setInteger("id", id);

  return q.list();

 }

适用情況:萬能方法,有點像ibatis輕量級架構的操作,友善維護。  缺點:不面向對象。基于hql和sql,有一定缺陷。

六、SQL查詢

   示例:

static List sql() {

 Session s = HibernateUtil.getSession();

  Query q = s.createSQLQuery("select * from user").addEntity(User.class);

  List<User> rs = q.list();

  s.close();

  return rs;

 }

适用情況:不熟悉HQL的朋友,又不打算轉資料庫平台的朋友,萬能方法   缺點:破壞跨平台,不易維護,不面向對象。

七、OID查詢方式

    按照對象的OID來檢索對象。Session的get()和load()方法提供了這種功能。如果在應用程式中事先知道了OID,就可以使用這種檢索對象的方式。 

八、Query.iterator的N+1查詢(基于一的HQL,多見于一對多、多對多的關聯映射)

  N + 1問題,在預設情況下,使用query.iterate查詢,有可以能出現N+1問題

   所謂的N+1是在查詢的時候發出了N+1條sql語句

   1: 首先發出一條查詢對象id清單的sql

   N: 根據id清單到緩存中查詢,如果緩存中不存在與之比對的資料,那麼會根據id發出相應的sql語句

* list和iterate的差別?

   * list每次都會發出sql語句,list會向緩存中放入資料,而不利用緩存中的資料

   * iterate:在預設情況下iterate利用緩存資料,但如果緩存中不存在資料有可以能出現N+1問題

  示例:Query q=session.createQuery(“from UserInfo”);

     Iterator<UserInfo> list=q.iterate();

     While(list.hasNext()) {

     UserInfo st = (UserInfo) it.next();

     System.out.println(st.getName());

    }

避免N+1查詢解決方法:

    1、可以将fetch抓取資料的屬性改為“join”,來避免N+1次的查詢;

    2、使用二級緩存

九、複查查詢(基于二:QBC的深度查詢)

  複合查詢就是在原有查詢的基礎上再進行查詢,可以調用Criteria對象的createCriteria()方法在這個Criteria對象的基礎上再進行查詢。

示例:Session session = SessionFactory.getCurrentSession();

    User user = new User();

    Transaction ts = session.beginTransaction();

    try  {

      Criteria criteria1 = session.createCriteria(Room.class);

      Criteria  criteria2 =criterial.createCriteria("User");

      criteria2.add(Restrictions.eq("name",new String("ijse"));

      user= (User) criteria.list().get(0);

      session.commit();

   } catch (HibernateException ex) {

      ts.rollBack();

      ex.printStackTrace();

   }

  System.out.println(user.getName());

最後,再說一下,Hibernate是可以執行存儲過程的。相關的文章我會在後續的文章中給出,請大家繼續關注.

繼續閱讀