Hibernate hql總結及BaseDao封裝
1.hql:Hibernate Query Language(Hibernate查詢語言)
作用:方便進行資料庫操作
2. hql和sql區別
1.hql是基於實體屬性進行查詢的;sql是基於表實體進行查詢的
2.hql區分大小寫,關鍵字不區分大小寫;sql不區分大小寫
3.hql是面向物件的查詢語言;sql是面向結構的查詢語言
4.hql佔位符下標從0開始(目前推薦使用:命名引數);sql佔位符下標從1開始
3.5種處理hql查詢返回的結果集
這裡以Book類為例項
/** * 結果處理一:當結果集為集合,查單個也可以通過這種方式,只不過不需要遍歷 */ @Test public void testList1() { String hql = "from Book"; Query query = session.createQuery(hql); List<Book> list = query.list(); for (Book book : list) { System.out.println(book); } } /** * 結果處理二:當結果集為集合,並且只查詢其中一列時 */ @Test public void testList2() { String hql = "select bookName from Book"; Query query = session.createQuery(hql); List<String> list = query.list(); for (String bname : list) { System.out.println(bname); } } /** * 結果處理三:當結果集為集合,並且查詢兩列及兩列以上,使用Object[] */ @Test public void testList3() { String hql = "select bookId,bookName from Book"; Query query = session.createQuery(hql); List<Object[]> list = query.list(); for (Object[] book : list) { System.out.println(Arrays.toString(book)); } } /** * 結果處理四:當結果集為集合,並且查詢兩列及兩列以上,使用hibernate內建函式 */ @Test public void testList4() { String hql = "select new map(bookId,bookName) from Book"; Query query = session.createQuery(hql); List<Map> list = query.list(); for (Map book : list) { System.out.println(book); } } /** * 結果處理五:當結果集為集合,並且查詢兩列及兩列以上,使用構造方法進行結果處理,記得提供對應構造器!! */ @Test public void testList5() { String hql = "select new Book(bookId,bookName) from Book"; Query query = session.createQuery(hql); List<Book> list = query.list(); for (Book book : list) { System.out.println(book); } }
4.hql的命名引數:等同於佔位符,推薦使用該方式
@Test public void testList6() { //此處的:bookIds相當於佔位符,不要漏掉: String hql = "from Book where bookId in (:bookIds)"; Query query = session.createQuery(hql); List<Integer> params = new ArrayList<Integer>(); params.add(1); params.add(2); //為bookIds賦值,也可以使用下標,hql的下標是從0開始 query.setParameterList("bookIds",params); List<Book> list = query.list(); for (Book book : list) { System.out.println(book); } }
5.使用hql完成聯表查詢
@Test public void testList7() { String hql = "select o.order_no,oi.product_id from Order o,OrderItem oi where o.order_id = oi.order.order_id"; //String hql = "select o.order_no,oi.product_id from Order o,OrderItem oi where o = oi.order"; Query query = session.createQuery(hql); List<Object[]> list = query.list(); for (Object[] obj : list) { System.out.println(Arrays.toString(obj)); } }
6.hql的聚合函式
sum avg max min count
這裡以count示例
@Test
public void testList8() {
String hql = "select count(*) from Book";
Query query = session.createQuery(hql);
Object obj = query.getSingleResult();
System.out.println(obj);
}
7.使用hql完成分頁
hql內部是有封裝分頁的,所以分頁不需要我們自己寫,只需要提供分頁資訊就行了
@Test
public void testList9() {
//資料庫為mysql
String hql = "from Book where bookName like :bookName";
int rows = 3;//每頁顯示3條記錄
int page = 1;//第一頁
Query query = session.createQuery(hql);
query.setParameter("bookName", "%紅%");//模糊查詢
query.setFirstResult((page-1)*rows);//從第幾條資料開始查,索引從0開始
query.setMaxResults(rows);
List<Book> list = query.list();
for (Book book : list) {
System.out.println(book);
}
}
8.對hql的操作進行封裝(BaseDao封裝):方便開發,減少冗餘程式碼
示例:帶條件的查詢分頁
public List<Book> list1(Book book,PageBean pageBean){
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
String hql = "from Book where 1=1";
if (StringUtils.isNotBlank(book.getBookName())) {
hql += " and book_name like :book_name";
}
Query query = session.createQuery(hql);
if (StringUtils.isNotBlank(book.getBookName())) {
query.setParameter("book_name", "%"+book.getBookName()+"%");
}
if (pageBean != null && pageBean.isPagination()) {
query.setFirstResult(pageBean.getStartPage());
query.setMaxResults(pageBean.getTotalPage());
}
List<Book> list = query.list();
return list;
}
注:setParameter方法是BaseDao封裝的設定引數方法,所以程式碼中減少了賦值的程式碼,這也是BaseDao的一個好處,後面會有程式碼,這裡主要看賦值以外的
從如上程式碼可以看到,隨著查詢條件的增加,那麼對應的if判斷就會很多,因此為了減少程式碼的冗餘,可以對其進行封裝
BaseDao封裝:
package com.study.dao;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.query.Query;
import com.zking.util.PageBean;
/**
* BaseDao作用:
* 1.特定值賦值
* 2.分頁
* 1.查總記錄數
* 2.查詢某一頁紀錄
* @author L
*
*/
public class BaseDao {
//1.引數賦值
public void setParameter(Query query,Map<String, Object> map) {
if (map == null || map.size() == 0) {
return;
}
Object value = null;
for (Map.Entry<String, Object> entry : map.entrySet()) {
value = entry.getValue();
if (value instanceof Collection) {
query.setParameterList(entry.getKey(), (Collection)value);
}
else if (value instanceof Object[]) {
query.setParameterList(entry.getKey(), (Object[])value);
}
else {
query.setParameter(entry.getKey(), value);
}
}
}
//2.1:統計記錄數
public String getCountHql(String hql) {
int index = hql.toUpperCase().indexOf("FROM");
return "select count(*) " + hql.substring(index);
}
//2.2:分頁
public List executeQuery(Session session,String hql,PageBean pageBean,Map<String, Object> map) {
if (pageBean != null && pageBean.isPagination()) {//是分頁
String countHql = getCountHql(hql);
Query countQuery = session.createQuery(countHql);
setParameter(countQuery, map);
pageBean.setTotal(Integer.valueOf(countQuery.getSingleResult().toString()));
Query pageQuery = session.createQuery(hql);
setParameter(pageQuery, map);
pageQuery.setFirstResult(pageBean.getStartPage());
pageQuery.setMaxResults(pageBean.getTotalPage());
return pageQuery.list();
}
else {//不分頁
Query query = session.createQuery(hql);
setParameter(query, map);
return query.list();
}
}
}
BaseDao封裝好後,再進行上個案例的操作:要記得繼承BaseDao
package com.study.dao;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import com.study.entity.Book;
import com.study.entity.TreeNode;
import com.zking.util.PageBean;
import com.zking.util.SessionFactoryUtils;
import com.zking.util.StringUtils;
public class BookDao extends BaseDao{
public List<Book> list2(Book book,PageBean pageBean){
Session session = SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
String hql = "from Book where 1=1";
Map<String, Object> map = new HashMap<String, Object>();
if (StringUtils.isNotBlank(book.getBookName())) {
hql += " and book_name like :book_name";
map.put("book_name", "%"+book.getBookName()+"%");
}
List list = executeQuery(session, hql, pageBean, map);
transaction.commit();
session.close();
return list;
}
}
程式碼簡潔了不少,至少我們成功去除了重複的程式碼
9.原生sql:
應用場景:當hql不滿足需求,或者使用hql不再簡化程式碼,想要使用sql程式碼時
將createQuery(hql)->createSQLQuery(sql)方法,就能使用sql程式碼了
10.檢視對映
例:
1.select * from book a,type b a.tid = b.tid where b.tname like '%玄%'
2.select * from book a,type b a.tid = b.tid where b.tid = 1
3.select * from book a,type b a.tid = b.tid where a.bname like '%完%'
以上是三條聯表查詢語句,因為業務不同,所以有時要對錶進行不同的查詢,如果聯表的數量非常多,那麼寫sql時程式碼就會非常長,所以檢視對映就是將重複sql程式碼封裝,然後根據不同的業務,只需要寫不同的條件即可
上述程式碼中重複的地方select * from book a,type b a.tid = b.tid
步驟
1.建立一個檢視,將此程式碼進行封裝
create view aaa
as
select * from book a,type b a.tid = b.tid
2.根據業務的不同,對檢視新增不同的查詢條件
假如我要根據書名查詢
select * form aaa where bname like '%完%'
這樣就可以達到簡化程式碼的作用