1. 程式人生 > >九、Hibernate的多種查詢方式

九、Hibernate的多種查詢方式

一、唯一標識OID的檢索方式

這種方式是通過主鍵來查詢的,呼叫方式如session.get(物件.class,OID),適用於獲取單條資料.

二、HQL的檢索方式

什麼是HQL
HQL(Hibernate Query Language) 是面向物件的查詢語言, 它和 SQL 查詢語言有些相似
在 Hibernate 提供的各種檢索方式中, HQL 是使用最廣的一種檢索方式。

HQL與SQL的關係
HQL 查詢語句是面向物件的,Hibernate負責解析HQL查詢語句, 然後根據物件-關係對映檔案中的對映資訊, 把 HQL 查詢語句翻譯成相應的 SQL 語句。
HQL 查詢語句中的主體是域模型中的類及類的屬性。
SQL 查詢語句是與關係資料庫繫結在一起的,SQL查詢語句中的主體是資料庫表及表的欄位。

注意:HQL語句的使用必須要開啟事務,即呼叫createQuery方法必須要先開啟事務,否則會報錯:
org.hibernate.HibernateException: createQuery is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:334)

HQL支援以下幾種查詢:
1.HQL基本的查詢格式


支援方法鏈的程式設計,即直接呼叫list()方法,例如:
session.createQuery("from Customer").list();//from後面寫的是類名而不是表名

2.使用別名的方式
session.createQuery("from Customer c").list();//as 可以省略
session.createQuery("select c from Customer c").list();

3.排序查詢
排序查詢和SQL語句中的排序的語法是一樣的
session.createQuery("from Customer order by cust_id").list(); //升序,預設asc可省略


session.createQuery("from Customer order by cust_id desc").list(); //降序

4.分頁查詢
Hibernate框架提供了分頁的方法,咱們可以呼叫方法來完成分頁,兩個方法如下
setFirstResult(index) //從哪條記錄開始,如果查詢是從第一條開啟,從0開始,取值參考(pageNo-1)*pageSize
setMaxResults(pageSize) //每頁查詢的記錄條數

例如獲取第一頁的資料,每頁有10條資料,可以這樣寫:
List<LinkMan> list = session.createQuery("from LinkMan").setFirstResult(0).setMaxResults(10).list();

5.帶條件的查詢
有3種方式:

  • 按位置繫結引數的條件查詢(指定下標值,預設從0開始)例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = ?");
	query.setLong(0, 2L);
	query.setString(1, "男");
	List<Linkman> list = query.list();
	...
  • 按名稱繫結引數的條件查詢(HQL語句中的 ? 號換成 :名稱 的方式),例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= :id and l.lkm_gender = :sex");
	query.setLong("id", 2L);
	query.setString("sex", "男");
	List<Linkman> list = query.list();
	...
  • setParameter("?號的位置,預設從0開始",“引數的值”); 不用考慮引數的具體型別
    或者setParameter(“繫結的名稱”,“引數的值”); 例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = :sex");
	query.setParameter(0, 2L);
	query.setParameter("sex", "男");
	List<Linkman> list = query.list();
	...

注意:條件查詢中的模糊查詢的%是寫在引數設定的方法裡的,例如:

	...
	Query query = session.createQuery("from Linkman l where l.lkm_name like ?");
	query.setParameter(0, "%o%"); //這裡填寫模糊查詢的表示式
	List<Linkman> list = query.list();
	...

6.投影查詢
投影查詢就是想查詢某一欄位的值或者某幾個欄位的值.返回的結果有兩種:

  • 返回陣列的集合
	...
	Query query = session.createQuery("select lkm_name,lkm_gender from Linkman");
	List<Object[]> list = query.list();//返回的是陣列的集合
	for (Object[] objects : list) {
		System.out.println(Arrays.toString(objects));
	}
	...

輸出的結果:
在這裡插入圖片描述

  • 返回javabean集合
    必須在javabean中提供指定欄位的構造方法,例如:
	public Linkman(String lkm_name, String lkm_gender) {
		this.lkm_name = lkm_name;
		this.lkm_gender = lkm_gender;
	}

	public Linkman() {
	}

然後HQL語句也要做相應變化,例如:

	...
	Query query = session.createQuery("select new Linkman(lkm_name,lkm_gender) from Linkman where lkm_gender=?");
	query.setParameter(0, "女");
	List<Linkman> list = query.list();// 返回的是物件的集合
	for (Linkman lm : list) {
		System.out.println(lm);
	}
	...

7.聚合函式查詢
HQL語句還能使用count() sum() avg() max() min()等聚合函式,例如:

/**
	 * avg聚合函式查詢
	 */
	@Test
	public void test10() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number型別接收的好處是方便型別轉換,lkm_id是Linkman 的屬性,而不是表的欄位
		List<Number> lis = session.createQuery("select avg(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).longValue());
		tr.commit();
	}
	
	/**
	 * max聚合函式查詢
	 */
	@Test
	public void test9() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number型別接收的好處是方便型別轉換,lkm_id是Linkman 的屬性,而不是表的欄位
		List<Number> lis = session.createQuery("select max(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}
	
	/**
	 * sum聚合函式查詢
	 */
	@Test
	public void test8() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number型別接收的好處是方便型別轉換,lkm_id是Linkman 的屬性,而不是表的欄位
		List<Number> lis = session.createQuery("select sum(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}
	/**
	 * count聚合函式查詢
	 */
	@Test
	public void test7() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number型別接收的好處是方便型別轉換,lkm_id是Linkman 的屬性,而不是表的欄位
		List<Number> lis = session.createQuery("select count(*) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}

三、QBC檢索方式

QBC:Query By Criteria 按條件進行查詢,非常適合用於條件查詢,完全面向物件的方式呼叫

注意:使用qbc查詢的前提也必須要開啟事務,即呼叫createCriteria方法必須要先開啟事務,否則回報如下錯誤:
org.hibernate.HibernateException: createCriteria is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invo

QBC查詢支援以下幾種查詢:
1.簡單查詢

/**
	 * QBC的基本入門查詢
	 */
	@Test
	public void test1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立QBC查詢介面
		Criteria criteria = session.createCriteria(Customer.class);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tr.commit();
	}

2.排序查詢
需要使用addOrder()的方法來設定引數,引數使用org.hibernate.criterion.Order物件的常量

/**
	 * QBC的排序查詢
	 */
	@Test
	public void test2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立QBC查詢介面
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.addOrder(Order.desc("cust_id"));//按照屬性cust_id降序排序
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tr.commit();
	}
	

3.分頁查詢
QBC分頁的方法和HQL分頁的方式一樣的,操作的是setFirstResult();和setMaxResults();這2個方法

/**
	 * QBC的分頁查詢
	 */
	@Test
	public void test3() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		Criteria criteria = session.createCriteria(Linkman.class);
		// 設定分頁查詢從第一條記錄開始(pageNo-1)*pageSize, 查詢3條資料,呼叫方式可以鏈式呼叫
		List<Linkman> list = criteria.setFirstResult(0).setMaxResults(3).list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}

		tr.commit();
	}

4.條件查詢
Criterion是查詢條件的介面,Restrictions類是Hibernate框架提供的工具類,使用該工具類來設定查詢條件,條件查詢使用Criteria介面的add方法來傳入條件,有以下條件可傳:

  • Restrictions.eq:相等
  • Restrictions.gt:大於號
  • Restrictions.ge:大於等於
  • Restrictions.lt:小於
  • Restrictions.le :小於等於
  • Restrictions.between:在之間
  • Restrictions.like:模糊查詢
  • Restrictions.in :範圍
  • Restrictions.and:並且
  • Restrictions.or:或者
  • Restrictions.isNull:空值查詢

例如:

/**
	 * QBC的條件查詢
	 */
	@Test
	public void test4() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		Criteria criteria = session.createCriteria(Linkman.class);
		//使用方法新增條件 
		criteria.add(Restrictions.eq("lkm_gender","男")); //等於男
		//lkm_id大於等於2,小於5
		criteria.add(Restrictions.and(Restrictions.ge("lkm_id",2L),Restrictions.lt("lkm_id",5L)));
		
		List<Linkman> list = criteria.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}
/**
	 * QBC的條件查詢之in查詢
	 */
	@Test
	public void test5(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立QBC查詢介面
		Criteria criteria = session.createCriteria(Linkman.class);
		
		// SQL:select * from cst_linkman where lkm_id in (1,2,5);
		List<Long> params = new ArrayList<Long>();
		params.add(1L);
		params.add(2L);
		params.add(5L);
		
		// 使用in 方法查詢
		criteria.add(Restrictions.in("lkm_id", params));
		
		List<Linkman> list = criteria.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}

5.聚合函式查詢
Projection的聚合函式的介面,而Projections是Hibernate提供的工具類,使用該工具類設定聚合函式查詢,常用的方法有:
在這裡插入圖片描述
例如:

/**
	 * QBC的聚合函式查詢
	 */
	@Test
	public void test6(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立QBC查詢介面
		Criteria criteria = session.createCriteria(Linkman.class);
		//聚合函式count使用
		criteria.setProjection(Projections.count("lkm_id"));
		
		List<Number> list= criteria.list();
		System.out.println(list.get(0).intValue());
		tr.commit();
	}
/**
	 * QBC的多次查詢
	 */
	@Test
	public void test8() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立QBC查詢介面
		Criteria criteria = session.createCriteria(Linkman.class);
		// 聚合函式count使用
		criteria.setProjection(Projections.count("lkm_id"));
		// 查詢count
		List<Number> list = criteria.list();
		System.out.println(list.get(0).intValue());

		// 重置projection
		criteria.setProjection(null);
		List<Linkman> lms = criteria.list();

		for (Linkman lm : lms) {
			System.out.println(lm);
		}
		tr.commit();
	}

提示:criteria.setProjection(null);也是有意義的,它是用於重置聚合函式的查詢條件,比如你想在一個方法裡面重複是用criteria.list();去查詢結果,由於第一次已經使用了聚合函式,第二次如果不想使用,可以直接呼叫criteria.setProjection(null);來重置.

四、離線條件查詢

離線條件查詢使用的是DetachedCriteria介面進行查詢,離線條件查詢物件在建立的時候,不需要使用Session物件,只是在查詢的時候使用Session物件即可。通常在web層就可以設定好查詢條件,然後傳入到service層使用,建立DetachedCriteria方式例如:
DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
然後就可以呼叫add方法新增各種條件了或者setProjection新增聚合函式,例如:

/**
	 * 離線查詢
	 */
	@Test
	public void test9() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立離線Criteria
		DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
		// 新增條件
		criteria.add(Restrictions.eq("lkm_gender", "女"));

		// 開始查詢
		List<Linkman> list = criteria.getExecutableCriteria(session).list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}

五、SQL查詢方式

如果喜歡手寫sql語句的朋友,可以使用這種方式,通過session.createSQLQuery(sql語句);的方式來執行sql查詢.例如:

/**
	 * 把資料封裝到物件中
	 */
	@Test
	public void test2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立的是SQL的查詢的介面
		SQLQuery query = session.createSQLQuery("select * from cst_linkman where lkm_gender = ?");
		// 通過該方法關聯實體類
		query.addEntity(Linkman.class);
		// 設定條件
		query.setParameter(0,"男");
		List<Linkman> list = query.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}

		tr.commit();
	}


	/**
	 * 測試SQL語句的查詢,輸出陣列集合
	 */
	@Test
	public void test1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 建立的是SQL的查詢的介面
		SQLQuery query = session.createSQLQuery("select * from cst_linkman");
		// 查詢資料
		List<Object[]> list = query.list();
		for (Object[] objects : list) {
			System.out.println(Arrays.toString(objects));
		}

		tr.commit();

	}