Hibernate查詢方法總結(包括條件分頁查詢、外來鍵id查詢)
每天進步一點點,最近做專案用到了很多的hibernate的查詢方法。正好騰出時間來總結,希望對自己和他人都有幫助。
首先非常感謝施楊 's think out 和suntao1983做的總結,幫我解決的很多問題。
hibernate 的 六種基本查詢方法:分別是HQL查詢,物件化查詢Criteria方法,動態查詢DetachedCriteria,例子查詢,sql查詢,命名查詢。
HQL查詢
HQL是hibernate自己的一套查詢語言,於SQL語法不同,具有跨資料庫的優點。示例程式碼:
static void query(String name){ Session s=null; try{ s=HibernateUtil.getSession(); //from後面是物件,不是表名 String hql="from Admin as admin where admin.aname=:name";//使用命名引數,推薦使用,易讀。 Query query=s.createQuery(hql); query.setString("name", name); List<Admin> list=query.list(); for(Admin admin:list){ System.out.println(admin.getAname()); } }finally{ if(s!=null) s.close(); } } 複製程式碼
適用情況:常用方法,比較傳統,類似jdbc。缺點:新的查詢語言,適用面有限,僅適用於Hibernate框架。
物件化查詢Criteria方法:
static void cri(String name,String password){ Session s=null; try{ s=HibernateUtil.getSession(); Criteria c=s.createCriteria(Admin.class); c.add(Restrictions.eq("aname",name));//eq是等於,gt是大於,lt是小於,or是或 c.add(Restrictions.eq("apassword", password)); List<Admin> list=c.list(); for(Admin admin:list){ System.out.println(admin.getAname()); } }finally{ if(s!=null) s.close(); } }
適用情況:面向物件操作,革新了以前的資料庫操作方式,易讀。缺點:適用面較HQL有限。
動態分離查詢DetachedCriteria
static List dc(DetachedCriteria dc) {
Session s = HibernateUtil.getSession();
Criteria c = dc.getExecutableCriteria(s);
List rs = c.list();
s.close();
return rs;
}
DetachedCriteria dc = DetachedCriteria.forClass(User.class); int id = 1; if (id != 0) dc.add(Restrictions.eq("id", id)); Date age = new Date(); if (age != null) dc.add(Restrictions.le("birthday", age)); List users = dc(dc); System.out.println("離線查詢返回結果:" + users);
適用情況:面向物件操作,分離業務與底層,不需要欄位屬性攝入到Dao實現層。 缺點:適用面較HQL有限。
例子查詢
static List example(User user) {
Session s = HibernateUtil.getSession();
List<User> users = s.createCriteria(User.class).add(
Example.create(user)).list();
// List<User>
// users2=s.createCriteria(User.class).add((Example.create(user)).ignoreCase())
// .createCriteria("child").add((Example.create(user))).list();
return users;
}
適用情況:面向物件操作。 缺點:適用面較HQL有限,不推薦。
sql查詢
static List sql() {
Session s = HibernateUtil.getSession();
Query q = s.createSQLQuery("select * from user").addEntity(User.class);
List<User> rs = q.list();
s.close();
return rs;
}
適用情況:不熟悉HQL的朋友,又不打算轉資料庫平臺的朋友,萬能方法 缺點:破壞跨平臺,不易維護,不面向物件。
命名查詢
static List namedQuery(int id) {
Session s = HibernateUtil.getSession();
Query q = s.getNamedQuery("getUserById");
q.setInteger("id", id);
return q.list();
}
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.sy.vo.User" table="user" catalog="news">
</class>
<!-- 命名查詢:定義查詢條件 -->
<query name="getUserById">
<![CDATA[from User where id=:id]]>
</query>
<!-- 命名查詢中使用sql,不推薦使用,影響跨資料庫
<sql-query name="getUserById2">
<![CDATA[select * from User where ]]>
</sql-query> -->
</hibernate-mapping>
複製程式碼
適用情況:萬能方法,有點像ibatis輕量級框架的操作,方便維護。 缺點:不面向物件。基於hql和sql,有一定缺陷。
通常使用的Hibernate通常是三種:hql查詢,QBC查詢和QBE查詢:
1、QBE(Qurey By Example)檢索方式
QBE是最簡單的,但是功能也是最弱的,QBE的功能不是特別強大,僅在某些場合下有用。一個典型的使用場合就是在查詢視窗中讓使用者輸入一系列的查詢條件,然後返回匹配的物件。QBE只支援=和like比較運算子,無法不大區間值,及其或的匹配。在這種情況下,還是採用HQL檢索方式或QBC檢索方式。
/**
* @function 根據傳遞過來的Object,分頁顯示在資料庫中與其匹配的記錄
* @param pageNo
* 當前頁數
* @param pageSize
* 每頁顯示的記錄數
* @param object
* 將查詢條件封裝為Object
* @return 將查詢結果封裝為Pager返回
*/
public Pager findPageByExample(int pageNo, int pageSize, Object object)
{
Pager pager = null;
try
{
Criteria criteria = this.getSession().createCriteria(
Class.forName(this.getEntity()));
if (object != null)
{
criteria.add(Example.create(object).enableLike());
}
// 獲取根據條件分頁查詢的總行數
int rowCount = (Integer) criteria.setProjection(
Projections.rowCount()).uniqueResult();
criteria.setProjection(null);
criteria.setFirstResult((pageNo - 1) * pageSize);
criteria.setMaxResults(pageSize);
List result = criteria.list();
pager = new Pager(pageSize, pageNo, rowCount, result);
} catch (RuntimeException re)
{
throw re;
} finally
{
return pager;
}
}
注意程式碼的第20行,即criteria.add(Example.create(object).enableLike());這一行,需將Example.create(object)呼叫.enableLike()方法,不然不能模糊查詢。
在BO層將需要模糊查詢的列用"%%"串起來,不然仍然和"="一樣。
BO層程式碼:
/**
* @function 將傳遞過來的引數封裝成搶修人員Bean,分頁查詢符合條件的記錄
* @param pageNo
* 當前的頁碼
* @param pageSize
* 每頁顯示的記錄數
* @param mendName
* 搶修人員的名稱
* @param specialty
* 搶修人員的工種
* @param post
* 搶修人員的職稱
* @return 將符合條件的記錄數以及頁碼資訊封裝成PagerBean返回
*/
public Pager getInfoByQuery(int pageNo, int pageSize, String mendName,
String specialty, String post)
{
EicMend eicMend = new EicMend();
if (mendName != null && mendName.length() > 0)
{
eicMend.setMendname("%" + mendName + "%");
}
if (specialty != null && specialty.length() > 0)
{
eicMend.setSpecialty(specialty);
}
if (post != null && post.length() > 0)
{
eicMend.setPost(post);
}
Pager pager = erpManagerDao
.findPageByExample(pageNo, pageSize, eicMend);
return pager;
}
2、QBC(Qurey By Criteria)檢索方式
採用HQL檢索方式時,在應用程式中需要定義基於字串形式的HQL查詢語句。QBC API提供了檢索物件的另一種方式,它主要由Criteria介面、Criterion介面和Restrictions介面組成,它支援在執行時動態生成查詢語句。比較常見的是兩種傳參方式:一種是用map傳參,另一種是用Criterion…不定引數傳參。
Map傳參方式範例如下:
DAO層:
/**
* @function 分頁顯示符合所有的記錄數,將查詢結果封裝為Pager
* @param pageNo
* 當前頁數
* @param pageSize
* 每頁顯示的條數
* @param map
* 將查詢條件封裝為map
* @return 查詢結果Pager
*/
public Pager findPageByCriteria(int pageNo, int pageSize, Map map)
{
Pager pager = null;
try
{
Criteria criteria = this.getSession().createCriteria(
Class.forName(this.getEntity()));
if (map != null)
{
Set<String> keys = map.keySet();
for (String key : keys)
{
criteria.add(Restrictions.like(key, map.get(key)));
}
}
// 獲取根據條件分頁查詢的總行數
int rowCount = (Integer) criteria.setProjection(
Projections.rowCount()).uniqueResult();
criteria.setProjection(null);
criteria.setFirstResult((pageNo - 1) * pageSize);
criteria.setMaxResults(pageSize);
List result = criteria.list();
pager = new Pager(pageSize, pageNo, rowCount, result);
} catch (RuntimeException re)
{
throw re;
} finally
{
return pager;
}
}
Map傳參方式對應BO層程式碼:
/**
* @function 將傳遞過來的引數封裝成搶修人員Bean,分頁查詢符合條件的記錄
* @param pageNo
* 當前的頁碼
* @param pageSize
* 每頁顯示的記錄數
* @param mendName
* 搶修人員的名稱
* @param specialty
* 搶修人員的工種
* @param post
* 搶修人員的職稱
* @return 將符合條件的記錄數以及頁碼資訊封裝成PagerBean返回
*/
public Pager getInfoByQuery2(int pageNo, int pageSize, String mendName,
String specialty, String post)
{
Map map = new HashMap();
if (mendName != null && mendName.length() > 0)
{
map.put("mendname", "%" + mendName + "%");
}
if (specialty != null && specialty.length() > 0)
{
map.put("specialty", specialty);
}
if (post != null && post.length() > 0)
{
map.put("post", post);
}
Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize, map);
return pager;
}
第二種方式:Criterion…不定引數傳參方式。其程式碼如下所示:
DAO層程式碼:
/**
* @function 分頁顯示符合所有的記錄數,將查詢結果封裝為Pager
* @param pageNo
* 當前頁數
* @param pageSize
* 每頁顯示的條數
* @param criterions
* 不定引數Criterion
* @return 查詢結果Pager
*/
public Pager findPageByCriteria(int pageNo, int pageSize,
Criterion... criterions)
{
Pager pager = null;
try
{
Criteria criteria = this.getSession().createCriteria(
Class.forName(this.getEntity()));
if (criterions != null)
{
for (Criterion criterion : criterions)
{
if (criterion != null)
{
criteria.add(criterion);
}
}
}
// 獲取根據條件分頁查詢的總行數
int rowCount = (Integer) criteria.setProjection(
Projections.rowCount()).uniqueResult();
criteria.setProjection(null);
criteria.setFirstResult((pageNo - 1) * pageSize);
criteria.setMaxResults(pageSize);
List result = criteria.list();
pager = new Pager(pageSize, pageNo, rowCount, result);
} catch (RuntimeException re)
{
throw re;
} finally
{
return pager;
}
}
Criterion…不定引數傳參方式對應BO層程式碼:
/**
* @function 將傳遞過來的引數封裝成搶修人員Bean,分頁查詢符合條件的記錄
* @param pageNo
* 當前的頁碼
* @param pageSize
* 每頁顯示的記錄數
* @param mendName
* 搶修人員的名稱
* @param specialty
* 搶修人員的工種
* @param post
* 搶修人員的職稱
* @return 將符合條件的記錄數以及頁碼資訊封裝成PagerBean返回
*/
public Pager getInfoByQuery3(int pageNo, int pageSize, String mendName,
String specialty, String post)
{
Criterion criterion1 = null, criterion2 = null, criterion3 = null;
if (mendName != null && mendName.length() > 0)
{
criterion1 = Restrictions.ilike("mendname", mendName,
MatchMode.ANYWHERE);
}
if (specialty != null && specialty.length() > 0)
{
criterion2 = Restrictions.ilike("specialty", specialty,
MatchMode.EXACT);
}
if (post != null && post.length() > 0)
{
criterion3 = Restrictions.ilike("post", post, MatchMode.EXACT);
}
Pager pager = erpManagerDao.findPageByCriteria(pageNo, pageSize,
criterion1, criterion2, criterion3);
return pager;
}
3、HQL檢索方式
HQL(Hibernate Query Language)是面向物件的查詢語言,它和SQL查詢語言有些相識。在Hibernate提供的各種檢索方式中,HQL是使用最廣的一種檢索方式。
使用Query介面分頁查詢DAO程式碼:
/**
* @function 分頁顯示符合所有的記錄數,將查詢結果封裝為Pager
* @param pageNo
* 當前頁數
* @param pageSize
* 每頁顯示的條數
* @param instance
* 將查詢條件封裝為專家Bean
* @return 查詢結果Pager
*/
public List<Object> findPageByQuery(int pageNo, int pageSize, String hql,
Map map)
{
List<Object> result = null;
try
{
Query query = this.getSession().createQuery(hql);
Iterator it = map.keySet().iterator();
while (it.hasNext())
{
Object key = it.next();
query.setParameter(key.toString(), map.get(key));
}
query.setFirstResult((pageNo - 1) * pageSize);
query.setMaxResults(pageSize);
result = query.list();
} catch (RuntimeException re)
{
throw re;
}
return result;
}
查詢所有記錄數的DAO程式碼:
/**
* @function 根據查詢條件查詢記錄數的個數
* @param hql
* hql查詢語句
* @param map
* 用map封裝查詢條件
* @return 資料庫中滿足查詢條件的資料的條數
*/
public int getTotalCount(String hql, Map map)
{
try
{
Query query = this.getSession().createQuery(hql);
Iterator it = map.keySet().iterator();
while (it.hasNext())
{
Object key = it.next();
query.setParameter(key.toString(), map.get(key));
}
Integer i = (Integer) query.list().get(0);
return i;
} catch (RuntimeException re)
{
throw re;
}
}
BO層程式碼:
/**
* @function 將傳遞過來的引數封裝成專家Bean,分頁查詢符合條件的記錄
* @param pageNo
* 當前的頁碼
* @param pageSize
* 每頁顯示的記錄數
* @param expertName
* 專家的名稱
* @param expertSpecialty
* 專家的專業類別
* @param post
* 專家的行政職位
* @return 將符合條件的記錄數以及頁碼資訊封裝成PagerBean返回
*/
public Pager getInfoByQuery(int pageNo, int pageSize, String expertName,
String expertSpecialty, String post)
{
StringBuffer hql = new StringBuffer();
hql.append("select count(expertid) from EicExpert where 1=1 ");
Map map = new HashMap();
if (expertName != null && expertName.length() > 0)
{
map.put("expertname", "%" + expertName + "%");
hql.append("and expertname like :expertname ");
}
if (expertSpecialty != null && expertSpecialty.length() > 0)
{
map.put("expertspecialty", expertSpecialty);
hql.append("and expertspecialty like :expertspecialty ");
}
if (post != null && post.length() > 0)
{
map.put("post", post);
hql.append("and post like :post ");
}
String queryHql = hql.substring(22);
List result = erpManagerDao.findPageByQuery(pageNo, pageSize,
queryHql, map);
int rowCount = erpManagerDao.getTotalCount(hql.toString(), map);
Pager pager = new Pager(pageSize, pageNo, rowCount, result);
return pager;
}
-
根據外來鍵條件分頁查詢
public List<ShProduct> findByBrand(int currentPage,int pageSize,int bid){
String hql = "from ShProduct model where model.shBrand.bid = :bid";
Session session = null;
List<ShProduct> list = null;
try {
session = getSession();
Query query = session.createQuery(hql);
query.setInteger("bid", bid);
query.setFirstResult((currentPage-1)*pageSize);
query.setMaxResults(pageSize);
list = query.list();
} catch (Exception e) {
e.printStackTrace();
} finally{
if(session!=null)
session.close();
}
return list;
}
歡迎關注公眾號,和我一起成長!