HQL的基本语法
2012-12-04 15:14
232 查看
HQL检索方式
HQL(Hibernate QueryLanguage)查询语言是面向对象的查询语言,也是在Hibernate中最常用的。其语法和SQL语法有些相似,功能十分强大,几乎支持除特殊SQL扩展外的所有查询功能。此种查询方式为Hibernate官方推荐的标准查询方式。
HQL的基本语法
HQL检索方式与SQL相似,使用方法基本相同;但HQL是面向对象查询语言,它查询的目标为对象,而SQL查询的目标则为数据表;除此之外,在书写HQL语句时要注意,它对大小写是敏感的。其基本语法如下:select “属性名” from “对象”
where “条件”
group by “属性名” having “分组条件”
order by “属性名” desc/asc
从上述基本语法可以看出,HQL与SQL的用法基本是一样的;但要注意,在使用HQL时在头脑中一定要有对象的概念。
例如:
select * from User u where u.id>10 order by u.iddesc
此语句将查询User对象所对应数据表中的记录,条件为id大于10,并将返回的结果集按id的降序进行排序,语句中的User为对象。
在HQL查询语句中,同样支持DML风格的语句,如update语句、delete语句,其使用方法与上述方法基本相同。不过,由于Hibernate缓存的存在,使用DML语句进行操作可能会造成与Hibernate缓存不同步的情况,从而导致脏数据的产生,所以在使用过程中应该尽量避免使用DML语句操作数据。
实体对象与动态实例化对象查询
þ 实体对象查询在HQL查询语句中,如果直接查询实体对象,不能使用select *子句的形式,但可以使用“from对象”的形式进行查询。
例如:
from User
上述HQL语句意味着查询User对象所对应数据表中的所有记录,使用此语句可获取已封装好的User对象的集合。
þ 动态实例化对象查询
在数据查询过程中,当数据表中存在大量的字段,如果通过“select*”的形式将所有字段都查询出来,将会对性能方面造成一定的影响。在HQL中,可以通过只查询所需要的属性进行查询。
例如:
select id, name from User
上述HQL语句只查询了User对象中的id与name属性,可以避免查询数据表中的所有字段而带来的性能方面的问题。但在Hibernate中,此语句返回的却是Object类型的数组,它失去了原有的对象状态,破坏了数据的封装性。要解决此问题,可以通过动态实例化对象来查询。
例如:
select new User(id,name) from User
这种查询方式通过new关键字对实体对象动态实例化,它可以对数据作出封装,既不失去数据的封装性,又可提高查询的效率。
例15.13 查询User对象中的所有数据。在UserDao类中编写findUser()方法,用于查询所有User对象。其关键代码如下:(实例位置:光盘TMInstances15.13)
//获取Session
session = HibernateUtil.getSession();
session.beginTransaction(); //开启事务
String hql = "fromUser"; //HQL语句
//创建Query对象
Query query = session.createQuery(hql);
list =query.list(); //获取查询结果集
//提交事务
session.getTransaction().commit();
HQL查询方式使用Query进行查询,其list()方法返回查询的结果,实例中将其输出到网页之中,其运行结果如图15.19所示。
图15.19 实例运行结果
条件查询与别名的使用
对于条件查询,在HQL语句中通过where子句来实现。例如:
from User where id = 1
此句用于实现查询id为1的User对象。
为了明确区分对象与对象中的属性,HQL提供了以下使用对象别名的方法。
þ 第一种方法:
from User u where u.id = 1
þ 第二种方法:
from User as u where u.id = 1
第二种方法与第一种方法相比,多了一个关键字as。
HQL语句的动态赋值
在JDBC编程中,PreparedStatement对象为开发提供了方便,它不但可为SQL语句进行动态赋值,而且可以避免SQL的注入式攻击;此外,由于它使用了SQL的缓存技术,还可以提高SQL语句的执行效率。在HQL查询语言中,也提供了类似的方法,其实现方式主要有两种。þ “?”号代表参数
此种方式与PreparedStatement极其相似,通过Query对象的setParameter()方法进行赋值,在HQL语句中以“?”号代表参数。如查询id为3的User对象,可以使用以下方法。
//HQL语句
String hql = "from User u where u.id =?";
//创建Query对象
Query query = session.createQuery(hql);
//HQL参数赋值
query = query.setParameter(0, 3);
//获取查询结果集
list = query.list();
þ 自定义参数名称
此种方式也通过Query对象的setParameter()方法进行赋值,但HQL语句中的参数可以自定义,它通过“:”号与自定义参数名组合的方法实现。如查询id为3的User对象,可以使用以下方法。
//HQL语句
String hql = "from User u where u.id =:userId";
//创建Query对象
Query query = session.createQuery(hql);
//HQL参数赋值
query = query.setParameter("userId", 3);
//获取查询结果集
list = query.list();
对象导航查询
HQL查询语言符合Java程序员的编程习惯,查询过程都以对象的方式进行操作,当一个对象与另一个对象存在依赖关系时,可以通过“.”符号进行导航。例15.14 对象导航查询。(实例位置:光盘TMInstances15.14)
编写名为Test的类,在此类中进行对象导航查询。其关键代码如下:
//获取Session
session = HibernateUtil.getSession();
//开启事务
session.beginTransaction();
//HQL查询语句
String hql = "from Medicine m where m.category.name = ?";
//创建Query对象并对HQL动态赋值
Query query = session.createQuery(hql)
.setParameter(0, "感冒用药");
//获取查询结果集
List<Medicine> list =query.list();
//循环输出类别"感冒用药"中的药品名称
for(Medicine m : list){
System.out.println("感冒用药: " + m.getName());
}
//提交事务
session.getTransaction().commit();
在本例中,查询了药品类别名称为“感冒用药”中的所有药品,并将药品的名称输出到控制台。其中使用“.”符号进行导航,其HQL语句中的m.category.name代表药品类别的名称。实例运行结果如图15.20所示。
图15.20 实例运行结果
排序查询
在获取数据结果集时,经常要对查询的结果集进行排序操作,以使其条理清晰、一目了然。HQL查询语言同样提供了此功能,主要是通过orderby子句来实现,对于排序类型使用asc、desc关键字。例如:
from User u order by id asc
此HQL语句可以实现查询User对象,并按id的升序排序。
例如:
from User u order by age desc
此HQL语句可以实现查询User对象,并按年龄的降序排序。
聚合函数
在HQL查询语言中,支持常用聚合函数的使用,如sum、count、max、min等,其使用方法与SQL中基本相同。如查询数据表中的记录,使用count(*)即可。例如:
select count(*) from User u
此HQL语句可以实现查询User对象所对应的数据表中的记录数。
例如:
select max(u.id) from User u
此HQL语句可以实现查询User对象所对应的数据表中的最大id值。
分组操作
在HQL查询语言中,通常使用groupby子句进行分组操作,其使用方法与SQL相似;此外,它也可以使用having关键字设置分组的条件。例15.15 编写一个名为Test的类,在main()方法中通过分组操作统计部门人数。其关键代码如下:(实例位置:光盘TMInstances15.15)
//获取Session
session = HibernateUtil.getSession();
session.beginTransaction(); //开启事务
//HQL语句
String hql = "select u.dept,count(*) from User u group byu.dept";
//创建Query对象
Query query = session.createQuery(hql);
//获取结果集
List<Object[]> list =query.list();
//循环输出部门名称及人数
for (Object[] obj : list) {
System.out.print("部门: " + obj[0] + "---");
System.out.println("人数: " + obj[1]);
}
//提交事务
session.getTransaction().commit();
在上述HQL语句中,count(*)用于统计部门的人数,group byu.dept表示通过部门进行分组。实例运行前,数据表中的数据如图15.21所示;实例运行后将输出部门的人数,如图15.22所示。
图15.21 员工信息表数据
图15.22 实例运行结果
对日期时间的处理
在HQL查询语言中,提供了多种对日期时间进行查询的方法,如可以使用“=”号进行时间的精确匹配,使用between…and子句查询指定的时间范围;此外,在HQL语句中还可以使用date_format()函数进行时间的模糊查询。例15.16 编写一个名为Test的类,在main()方法中查询1984年1月出生的用户。其关键代码如下:(实例位置:光盘TMInstances15.16)
//获取Session
session = HibernateUtil.getSession();
session.beginTransaction(); // 开启事务
//HQL语句
String hql = "from User u where date_format(u.birth,'%Y-%m') =?";
//创建Query对象
Query query = session.createQuery(hql)
.setParameter(0, "1984-01");
//获取结果集
List<User> list =query.list();
System.out.println("1984年1月出生的用户有:");
//循环输出1984年1月出生的用户姓名及出生日期
for (User user : list) {
System.out.print("姓名: " + user.getName() + "t");
System.out.println("出生日期: " + user.getBirth());
}
//提交事务
session.getTransaction().commit();
在上述HQL语句中,date_format(u.birth,'%Y-%m')用于格式化用户的出生日期。在实例运行前,数据表中的数据如图15.21所示;实例运行后将输出1984年1月出生的用户,如图15.23所示。
图15.23 实例运行结果
联合查询
在对多表进行查询时,经常用到联合查询,通过它可以方便地对多表中的数据进行快速检索。与SQL相同,HQL同样支持这种机制。在HQL中,可以使用内连接、外连接及全连接对多表进行联合操作,其使用方式如表15.2所示。表15.2 HQL联合查询方式说明
查 询 方 式 | 说 明 |
内连接 | 使用inner join子句,可以简写为join |
左外连接 | 使用left outer join子句,可以简写为left join |
右外连接 | 使用right outer join子句,可以简写为right join |
全连接 | 使用full join子句 |
例如:
from Student s left join s.classes c with c.id >10
例15.17 使用内连接查询药品信息及所属类别的名称。(实例位置:光盘TMInstances15.17)
在本例中编写药品数据库操作类MedDao,在此类中通过findMedAndCategory()方法进行内连接查询。其关键代码如下:
public List<Object[]>findMedAndCategory() {
Session session = null; //声明Session对象
List<Object[]> list = null;
try {
//获取Session
session = HibernateUtil.getSession();
//开启事务
session.beginTransaction();
//HQL查询语句
String hql = "select m.id,m.name,m.price,m.factoryAdd,c.name fromMedicine m inner join m.category c";
//创建Query对象并获取结果集
list = session.createQuery(hql)
.list();
//提交事务
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//出错将回滚事务
session.getTransaction().rollback();
} finally {
//关闭Session对象
HibernateUtil.closeSession(session);
}
return list;
}
在上述HQL语句中,m.category c是指药品对象的所属类别。实例运行结果如图15.24所示。
图15.24 实例运行结果
子查询
功能强大的HQL查询语言,几乎支持除SQL中一些特殊扩展功能外的所有查询方式,对于子查询在HQL中也是可以使用的。例15.18 使用子查询查询药品对象中最贵的药品名称。(实例位置:光盘TMInstances15.18)
编写名为Test的类,在此类中通过main()方法进行查询。其关键代码如下:
//获取Session
session = HibernateUtil.getSession();
session.beginTransaction(); //开启事务
// HQL语句
String hql = "select med.name from Medicine med where med.price= (select max(price) from Medicine)";
//获取结果集
List<String> list =session.createQuery(hql).list();
//循环输出最贵的药品
for (String name : list) {
System.out.println("最贵的药品为: " + name);
}
//提交事务
session.getTransaction().commit();
在上述HQL语句中,其子句select max(price) fromMedicine用于查询药品对象中最贵的价格,然后查询价格等于此价格的药品的名称
相关文章推荐
- HQL的基本语法
- Hibernate 查询语句HQL基本语法
- HQL语言基本语法
- HQL语句的基本语法和使用
- HQL的基本语法
- HBERNATE查询语句(HQL)基本语法
- Hibernate中的HQL基本语法
- Hibernate 查询语句HQL基本语法
- plsql配置 orcale基本语法 中文乱码
- Velocity模板引擎的介绍和基本的模板语言语法使用
- javascript基本语法6 其他引用类型对象
- 多表查询基本语法
- Java程序员从笨鸟到菜鸟之(十八)JSP基本语法与动作指令
- varnish缓存二:VCL基本语法
- scala学习(2)-基本语法--for循环和if语句
- Shell第三篇:基本语法
- Python学习(一)基本语法
- HTML的基本结构语法 表格, 框架, 表单
- 脚本的基本语法
- C++语法一(概述,程序基本元素,数据类型)