九、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();
}