天天看點

【Hibernate之Hql語句五】前言總結

目錄

  • 前言
    • Hql的介紹
    • Hql語句的特性
      • HQL語句支援占位符
      • HQL支援連接配接查詢
      • HQL支援聚合函數
      • HQL分頁
    • Hql特性的運用(模糊查詢,分頁)
      • 運用基本特性邏輯
      • 運用輔助Dao方法減少開發周期(BaseDao)
  • 總結

前言

本章節我們将會通過結合之前的案例來詳細講解一下Hql語句的運用。

比如

【Hibernate之Hql語句五】前言總結

在裡面的 “from Order” 這就算是Hql語句的一種

那麼查詢所有,用這種方法就可以實作,那麼問題就這麼來了,

如果我想傳個參數,然後根據參數查詢,或者用來分頁,那麼這個時候Hql語句又如何去寫?

歐克,Let`go

Hql的介紹

Hql: 簡稱Hibernate的面向對象語言

Hibernate Query Language的縮寫

那麼讓我們來看一看Hql和sql語句的差別。

HQL SQL
類名/屬性 表名/列名
區分大小寫,關鍵字不區分大小寫 不區分大小寫
别名 别名
?,從下标0開始計算位置(hibernate5之後不支援) ?,從順序1開始計算位置
:命名參數 不支援:命名參數
面向對象的查詢語言 面向結構查詢語言

嘛,接下來就是一整套的測試資料

Hql語句的特性

傳回對象(多個)

public void testList1() {
		Query query = session.createQuery("from Book");
		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

傳回單個列段,用字元串就可以接受

public void testList2() {
		Query query = session.createQuery("select b.bookName as ss from Book b");
		List<String> list = query.list();
		for (String b : list) {
			System.out.println(b);
		}
	}
           

查兩個列段及以上,預設傳回的是Object【】

public void testList3() {
		Query query = session.createQuery("select b.bookId,b.bookName as ss from Book b");
		List<Object[]> list = query.list();
		for (Object[] b : list) {
			System.out.println(Arrays.toString(b));
		}
	}
           

注意map是函數,是以不區分大小寫,傳回的是map集合

public void testList4() {
		Query query = session.createQuery("select new mAp(b.bookId,b.bookName) from Book b");
		List<Map> list = query.list();
		for (Map b : list) {
			System.out.println(b);
		}
	}
           

查兩個列段及以上,也可傳回對象,前提是有對應的構造函數

public void testList5() {
		Query query = session.createQuery("select new Book(b.bookId,b.bookName) from Book b");
		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

HQL語句支援占位符

public void testList6() {

		Query query = session.createQuery("from Book where bookId in (:bookIds)");
		query.setParameterList("bookIds", new Integer[] {1,2,4});

		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

HQL支援連接配接查詢

public void testList7() {
		Query query = session.createQuery("select o.orderNo,oi.quantity from Order o,OrderItem oi where o = oi.order");
		List<Object[]> list = query.list();
		for (Object[] b : list) {
			System.out.println(Arrays.toString(b));
		}
	}
           

HQL支援聚合函數

public void testList8() {
		Query query = session.createQuery("select count(*) from Book");
		Long singleResult = (Long) query.getSingleResult();
		System.out.println(singleResult);
	}
           

HQL分頁

public void testList9() {
		Query query = session.createQuery("from Book");
		query.setFirstResult(2);
		query.setMaxResults(3);
		List<Book> list = query.list();
		for (Book b : list) {
			System.out.println(b);
		}
	}
           

Hql特性的運用(模糊查詢,分頁)

運用基本特性邏輯

通過上面的特性講解,大概也了解了基本特性

是以我們就可以來寫個方法來測試是否可以使用模糊查詢。

為了大家了解,就不直接放代碼,而是一步一步來。

一,根據參數的有無而拼接hql語句

一般而言我們是直接從request請求中擷取map集合裡面的參數

可這邊因為是測試,是以沒有前端這一說。

切記不要搞混了!!!

//擷取參數
String bookName = book.getBookName();

String Hql = "from Book where 1=1 ";

//根據參數的有無而拼接hql語句,所用的是命名參數
if(StringUtils.isNotBlank(bookName)) {
	Hql+=" and bookName like :bookname ";
}
           

裡面的 :bookname 是命名參數的寫法 ,也就是已鍵值對的方式存在.

二,下面需要對query所指派

ok,在我的看法中,我就直接分為兩個部分,在這個部分中就是對query所指派

橫豎都是指派,隻不過需要在指派之前加個判斷

//下面需要對query所指派
Query query = session.createQuery(Hql);

if(StringUtils.isNotBlank(bookName)) {
	query.setParameter("bookname", "%"+bookName+"%");
}

//判斷是否需要分頁
if(pageBean!=null && pageBean.isPagination()) {
	query.setFirstResult(pageBean.getStartIndex());
	query.setMaxResults(pageBean.getRows());
}
		
           

三,整體代碼展示

其實如果把之前的查詢所有,和我剛才講的來想一想的話其實還是差不多的。

偌:

public List<Book> list1(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		

		String Hql = "from Book where 1=1 ";

		//下面需要對query所指派
		Query query = session.createQuery(Hql);
		List<Book> list = query.list();
		
		transaction.commit();
		session.close();
		return list;
	}
	
           

啊啊,整體代碼就是這樣:

public List<Book> list1(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		//擷取參數
		String bookName = book.getBookName();
		
		String Hql = "from Book where 1=1 ";
		
		//根據參數的有無而拼接hql語句
		if(StringUtils.isNotBlank(bookName)) {
			Hql+=" and bookName like :bookname ";
		}
		
		//下面需要對query所指派
		Query query = session.createQuery(Hql);
		
		if(StringUtils.isNotBlank(bookName)) {
			query.setParameter("bookname", "%"+bookName+"%");
		}
		
		//判斷是否需要分頁
		if(pageBean!=null && pageBean.isPagination()) {
			query.setFirstResult(pageBean.getStartIndex());
			query.setMaxResults(pageBean.getRows());
		}
		
		List<Book> list = query.list();
		
		transaction.commit();
		session.close();
		return list;
	}
	
           

希望大家能看的懂,也能了解我的思路拉(✪ω✪)

運用輔助Dao方法減少開發周期(BaseDao)

在上面我們已經知道如何裸寫代碼了,那麼這個還怕個啥子嘛。

那麼為了了解,我就先給大家看寫好後,所引用的Dao

是不是看到後,感覺是不是跟我的上面分解第一步差不多,隻不過整體上沒有了第二部分的代碼

ps:用到了map那是因為是用來模拟從jsp所傳值,請不要亂想!!

public List<Book> list2(Book book,PageBean pageBean) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		
		//擷取參數
		String bookName = book.getBookName();
		
		String Hql = "from Book where 1=1 ";
		Map<String, Object> map = new HashMap<>();
		
		//根據參數的有無而拼接hql語句
		if(StringUtils.isNotBlank(bookName)) {
			Hql+=" and bookName like :bookname ";
			map.put("bookname", bookName);
		}
		
		List<Book> list = executeQuery(session, map, Hql, pageBean);
		
		transaction.commit();
		session.close();
		return list;
	}
           

1,BaseDao中的一鍵指派(輔助方法)

這個家夥的話大家也别到處亂想了,汗,

方法本身主要是在本類裡面使用,作用:快速給query指派

map是外面所傳過來的,咱先不管是否是jsp傳過來,還是自己建立的map集合。

這個就是将Map集合裡面的資料全部給query指派

public void setParam(Map<String, Object> map , Query query) {
		
		if(map!=null&&map.size()>0) {
			Set<Entry<String, Object>> entrySet = map.entrySet();
			Object value = null;
			for (Entry<String, Object> entry : entrySet) {
				value = entry.getValue();
				//擷取來自參數的map的鍵值對
				//判斷每一個的值的類型然後分别對待
				if(value instanceof Object[]) {
					query.setParameterList(entry.getKey(), (Object[])value);
				}
				else if(value instanceof Collection) {
					query.setParameterList(entry.getKey(), (Collection)value);
				}
				else {
					query.setParameter(entry.getKey(), value);
				}
				
			}
		}
	}
           

2,BaseDao中的查詢總行數(輔助方法)

這個比較簡單,就是根據Hql去查詢表内總行數

public String getCountHql(String Hql) {
		
		int indexOf = Hql.toUpperCase().indexOf("FROM");
		return "select count(*)  "+Hql.substring(indexOf);
	}
           

3,所使用方法和判斷是否分頁(引用方法)

這個,其實并不難,重點在需要分頁的裡面

它使用了兩次 seesion.createQuery ,不明白的話就會搞混了,

其實就是給pageBean的total屬性所指派。

額,怎麼說呢,就是因為你模糊查詢後,所查到的資料絕對不是整張表的的條數嘛,

是以需要重新設定一下,

public List executeQuery(Session session,Map<String, Object> map,String Hql,PageBean pageBean ) {
		List list = null;
		if(pageBean!=null && pageBean.isPagination()) {
			
			//------找到這個表内有多少資料
			String countHql = this.getCountHql(Hql);
			Query countQuery = session.createQuery(countHql);
			this.setParam(map, countQuery);
			pageBean.setTotal(countQuery.getSingleResult().toString());
			
			//----------------------------------
			//給需要分頁的query設定值
			Query query = session.createQuery(Hql);
			query.setFirstResult(pageBean.getStartIndex());
			query.setMaxResults(pageBean.getRows());
			
			this.setParam(map, query);
			list = query.list();
			
		}
		else {//不用分頁的話
			Query query = session.createQuery(Hql);
			//給query的參數指派
			this.setParam(map, query);
			list = query.list();
			
		}
		
		return list;
	}
           

總結

哇,超額完成啊,有木有,

這次是我想一下,看能不能改一下風格滴,

本人覺得每個地方的講解還算詳細的啦|ू・ω・` )

Thanks♪(・ω・)ノ希望對大家有所幫助

繼續閱讀