目錄
- 前言
-
- Hql的介紹
- Hql語句的特性
-
- HQL語句支援占位符
- HQL支援連接配接查詢
- HQL支援聚合函數
- HQL分頁
- Hql特性的運用(模糊查詢,分頁)
-
- 運用基本特性邏輯
- 運用輔助Dao方法減少開發周期(BaseDao)
- 總結
前言
本章節我們将會通過結合之前的案例來詳細講解一下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♪(・ω・)ノ希望對大家有所幫助