hibernate中支持三种查询方式:HQL(Hibernate Query Language),原生sql查询,Criteria查询。HQL是一种面向对象的查询语言,其中没有表和字段的概念,只有类、对象、属性的概念;原生sql查询就是我们程序员手动的写sql语句并执行;Criteria查询又称为对象查询,采用真正的面向对象的方式进行查询,Criteria查询将在后续篇章中进行单独讲解,本篇文章只讲解HQL查询和原生sql查询。
环境:
本篇及后续文章都将使用Oracle数据库、oracle自带的两张数据表Dept和Emp以及Hibernate4为例进行讲述
一、HQL查询
1.HQL语句的组成
①from子句
最为简单的查询语句,比如:
- from Dept
②select子句
主要用于选取对象的属性(投影),如:
- select deptNo from Dept
③where子句
用于添加查询条件,如:
- from Dept where deptNo=2
一般用在where子句中,如:
- from Dept where lower(deptName)='sales'
用于按照指定属性进行排序,如:
- from Emp order by hireDate asc
a.from后面跟的都不是表的名字,而是表对应的实体类的名字,必须完全一致;相应的,语句中的deptName、deptNo等都是 实体类属性的名字,而不是表中列的名字
b.可以为实体类起别名,如:from Dept d where d.deptNo=2
c.select、from、where...等关键词不区分大小写,实体类和属性名要完全一致
2.执行HQL语句
介绍了如何编写HQL语句,下面来介绍下如何来执行。HQL的查询是通过Hibernate的Query接口来实现的
- //准备HQL语句
- String hql="from Dept";
- //使用createQuery()方法来创建Query接口实现类
- Query query=session.createQuery(hql);
①使用list()方法
- public static void main(String[] args) {
- Session session=HibernateUtil.currentSession();
- Transaction tx=session.beginTransaction();
- //准备HQL语句
- String hql="from Dept";
- //使用createQuery()方法来创建Query接口实现类
- Query query=session.createQuery(hql);
- List<Dept> list=query.list();
- for (Dept dept : list) {
- System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
- }
- tx.commit();
- HibernateUtil.closeSession();
- }
Hibernate:
select
dept0_.DEPTNO as DEPTNO0_,
dept0_.DNAME as DNAME0_,
dept0_.LOC as LOC0_
from
MYDEPT dept0_
50 vacant
60 test2
10 ACCOUNTING
20 RESEARCH
30 SALES
40 OPERATIONS
②使用iterate()方法
- public static void main(String[] args) {
- Session session=HibernateUtil.currentSession();
- Transaction tx=session.beginTransaction();
- //准备HQL语句
- String hql="from Dept";
- //使用createQuery()方法来创建Query接口实现类
- Query query=session.createQuery(hql);
- Iterator<Dept> list=query.iterate();
- Dept dept=null;
- while (list.hasNext()) {
- dept = list.next();
- System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
- }
- tx.commit();
- HibernateUtil.closeSession();
- }
Hibernate:
select
dept0_.DEPTNO as col_0_0_
from
MYDEPT dept0_
Hibernate:
select
dept0_.DEPTNO as DEPTNO0_0_,
dept0_.DNAME as DNAME0_0_,
dept0_.LOC as LOC0_0_
from
MYDEPT dept0_
where
dept0_.DEPTNO=?
10 ACCOUNTING
Hibernate:
select
dept0_.DEPTNO as DEPTNO0_0_,
dept0_.DNAME as DNAME0_0_,
dept0_.LOC as LOC0_0_
from
MYDEPT dept0_
where
dept0_.DEPTNO=?
20 RESEARCH
.
.
.
从生成的sql语句可以看出,使用list()方法是先查询所有符合条件的记录;而iterate()方法是首先查询出所有符合条件的主键值(如:deptNo),然后在需要某一对象的其他
属性值的时候再发送sql语句进行查询;
这就是Hibernate的HQL查询,关于where子句、order by等子句的使用就不做过多的解释了(条件查询的参数传递可以留作疑问)大同小异,童鞋们可以自己去多试试,多练练。
二、原生sql查询
原生sql查询同样使用了Query接口,使用session.createSQLQuery()方法可以返回一个SQLQuery对象,SQLQuery接口继承了Query接口, 在原生sql查询中就要对应的写表名和对应的列名了,而不是实体类和属性名,下面看依照HQL查询进行编码:
- public static void main(String[] args) {
- Session session=HibernateUtil.currentSession();
- Transaction tx=session.beginTransaction();
- //编写sql语句
- String sql="select * from dept";
- //使用createSQLQuery()方法
- Query query=session.createSQLQuery(sql);
- List<Dept> list=query.list();
- for (Dept dept : list) {
- System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
- }
- tx.commit();
- HibernateUtil.closeSession();
- }
select
*
from
dept
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.wzj.entity.Dept
at com.wzj.test.TestMain.main(TestMain.java:43)
- //编写sql语句
- String sql="select * from dept";
- //使用createSQLQuery()方法
- Query query=session.createSQLQuery(sql);
- List<Object[]> list=query.list();
- for (Object[] dept : list) {
- System.out.println(dept[0]+"\t"+dept[1]);
- }
为了使查询的数据直接封装成Dept对象,Hibernate的 SQLQuery接口提供了addEntity()方法来将关系数据转换成对象型数据:
- //编写sql语句
- String sql="select * from dept";
- //注意addEntity()方法是SQLQuery接口特有的,使用query是调用不出来的
- Query query=session.createSQLQuery(sql).addEntity(Dept.class);
- List<Dept> list=query.list();
- for (Dept dept : list) {
- System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
- }
此外, SQLQuery接口还提供了addJoin()方法来进行连接查询:
- String sql="select e.*,d.* from EMP e join DEPT d on d.deptno=e.deptno";
- Query query=session.createSQLQuery(sql).addEntity("e",Emp.class)
- .addJoin("d","e.dept");
- //连接查询返回Object数组类型,第一个是元素是Emp对象,第二个是Dept对象
- List<Object[]> list=query.list();
- Emp emp=null;
- Dept dept=null;
- for (Object[] o : list) {
- emp=(Emp)o[0];
- dept=(Dept)o[1];
- System.out.println(emp.getEmpName()+"\t"+dept.getDeptName());
- }
运行结果:
select
e.*,
d.*
from
EMP e
join
DEPT d
on d.deptno=e.deptno
CLARK ACCOUNTING
KING ACCOUNTING
MILLER ACCOUNTING
JONES RESEARCH
FORD RESEARCH
ADAMS RESEARCH
SMITH RESEARCH