您的位置:首页 > 其它

Hibernate查询方法总结(包括条件分页查询、外键id查询)

2013-04-18 15:24 525 查看
每天进步一点点,最近做项目用到了很多的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分页查询小结

通常使用的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(Examp
4000
le.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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Hibernate 分页