序言

         之前对hibernate中的查询总是搞混淆,不明白里面具体有哪些东西。就是因为缺少总结。在看这篇文章之前,你应该知道的是数据库的一些查询操作,多表查询等,如果不明白,可以先去看一下 MySQL数据表查询操作详解  ,以至于看这篇文章不用那么吃力。

                                            --WZY

一、hibernate中的5种检索方式

      1.1、导航对象图检索方式  

          根据已经加载的对象导航到其他对象

          例如:在前面的各种映射关系中,实体类包含对其他类对象的引用。

              Dept d = (Dept) session.get(Dept.class,2);

              d.getStaffSet().size();  //d对象关联Staff集合,hibernate会自动检索Staff数据。如何检索的,看下面图中发送的sql语句。

                       

      1.2、OID检索方式

          按照对象的OID来检索对象

          例如:session.get()/session.load()  

          这个大家度很熟悉了,就不用在这里过多的阐述了。

      1.3、HQL检索方式

          HQL:Hibernate Query Language ,是面向对象的查询语言,它和SQL查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用的最广的一种检索方式,

              注意:HQL操作的全是POJO类中的属性,而不是操作数据库表中的字段。

          1.3.1、在查询语句中设定各种查询条件

          1.3.2、支持投影查询,即仅检索出对象的部分属性

          1.3.3、支持分页查询

          1.3.4、支持连接查询

          1.3.5、支持分组查询,允许使用HAVING 和 GROUP BY 关键字

          1.3.6、提供内置聚集函数,如SUM(),MIN(),MAX()等

          1.3.7、能够调用用户定义的SQL函数或标准的SQL函数

          1.3.8、支持子查询

          1.3.9、支持动态绑定参数

          使用HQL检索步骤:

              1>获得session

              2>编写HQL

              3>通过session.createQuery(HQL)创建Query对象

              4>为Query对象设置条件参数(如果HQL中需要填充参数的话)

              5>执行查询

                  list():返回一个集合列表,有可能集合中装的是数组,有可能是POJO对象。

                  uniqueResult():返回一个查询结果,在已知查询结果只有一个或者0个时,使用是没有问题的,如果返回结果有多个,那么就会报异常

          实验

          创建环境,使用Dept和Staff的双向一对多关系,其中具体的代码就不在列举出来了。重点不在这里。原始记录Staff中有9条记录,都指向了Dept中id为2的部门。

           1.3.1、在查询语句中设定各种查询条件    

                 1.3.1.1、查询全部记录,没有查询条件         

         //没有条件的hql,也就是查询全部记录。
String hql = "from Staff";
Query hqlQuery = session.createQuery(hql);
List<Staff> list = hqlQuery.list();
for(Staff staff : list){
System.out.println(staff.toString());
}

  

                 结果

              

                

                1.3.1.2、条件查询,查找出id=3的staff信息

         String hql = "from Staff where id = 3";
Query hqlQuery = session.createQuery(hql);
//方式一
// List<Staff> list = hqlQuery.list();
// for(Staff staff : list){
// System.out.println(staff.toString());
// }
//方式二,已知只有一条数据,使用uniqueResult
Staff staff = (Staff) hqlQuery.uniqueResult();
System.out.println(staff.toString()); //结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
where
staff0_.id=3
//因为是立即检索,所有有了这条语句,这里不做解释,
Hibernate:
select
dept0_.id as id0_0_,
dept0_.name as name0_0_
from
dept dept0_
where
dept0_.id=?
//查询到了响应结果
Staff [id=3, name=qqq2, dept=oneToMany.Dept@cc0e21a]

   

           1.3.2、支持投影查询,即仅检索出对象的部分属性

                  也就是不需要将表中所有的字段度查询出来,只查询出对象的部分属性,这就是投影查询

                1.3.2.1、什么度不使用,直接查询,得到的结果就是将查到的属性全放到list集合中。这只使用于检索对象的一个属性,如果多个属性,就得需要用别的方式进行封装

         String hql = "select name from Staff";
Query hqlQuery = session.createQuery(hql);
List list = hqlQuery.list(); //集合中存放的是String,也就是name属性值。
System.out.println(list); //结果
Hibernate:
select
staff0_.name as col_0_0_
from
staff staff0_
[qqq1, qqq2, qqq3, qqq4, qqq5, qqq6, qqq7, qqq8, qqq9]

                1.3.2.2、使用new List()或者new Map()或new Staff()将返回的值给封装起来

    使用new Staff()

         //使用new Staff(id,name)的前提是Staff的实体类中id和name这个构造器。反则报错
String hql = "select new Staff(id,name) from Staff";
Query hqlQuery = session.createQuery(hql);
List<Staff> list = hqlQuery.list(); //集合中存放的是Staff数组。。
System.out.println(list);
//结果
Hibernate:
select
staff0_.id as col_0_0_,
staff0_.name as col_1_0_
from
staff staff0_
[Staff [id=2, name=qqq1, dept=null], Staff [id=3, name=qqq2, dept=null], Staff [id=4, name=qqq3, dept=null], Staff [id=5, name=qqq4, dept=null],
Staff [id=6, name=qqq5, dept=null], Staff [id=7, name=qqq6, dept=null], Staff [id=8, name=qqq7, dept=null], Staff [id=9, name=qqq8, dept=null],
Staff [id=10, name=qqq9, dept=null]]

    使用new List()

         //将查询到的结果存放在list集合中,形式如 List[数组1,数组2...]  数组1[id,name]
String hql = "select new List(id,name) from Staff";
Query hqlQuery = session.createQuery(hql);
List list = hqlQuery.list(); //集合中存放的是id,name数组。。
System.out.println(list); //结果
Hibernate:
select
staff0_.id as col_0_0_,
staff0_.name as col_1_0_
from
staff staff0_
[[2, qqq1], [3, qqq2], [4, qqq3], [5, qqq4], [6, qqq5],
[7, qqq6], [8, qqq7], [9, qqq8], [10, qqq9]]

    使用new Map()

        //将查询到的结果用map封装,然后放到list集合中,
String hql = "select new Map(id,name) from Staff";
Query hqlQuery = session.createQuery(hql);
List list = hqlQuery.list(); //集合中存放的是id,name数组。。
System.out.println(list); //结果
Hibernate:
select
staff0_.id as col_0_0_,
staff0_.name as col_1_0_
from
staff staff0_
[{1=qqq1, 0=2}, {1=qqq2, 0=3}, {1=qqq3, 0=4},
{1=qqq4, 0=5}, {1=qqq5, 0=6}, {1=qqq6, 0=7},
{1=qqq7, 0=8}, {1=qqq8, 0=9}, {1=qqq9, 0=10}]

            1.3.3、支持分页查询

                使用setFirst()和setMaxResult()分别设置起始索引和拿去数据的总数。跟limit m,n 是一样的

        String hql = "from Staff";
Query hqlQuery = session.createQuery(hql);
//从数据库表中取出第三条到第六条记录来。相当于MySQL的limit 2,3;
hqlQuery.setFirstResult(2);
hqlQuery.setMaxResults(3);
List<Staff> list = hqlQuery.list(); //集合中存放的是id,name数组。。
for(Staff staff : list){
System.out.println(staff.toString());
} //结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_ limit ?,
?
Hibernate:
select
dept0_.id as id0_0_,
dept0_.name as name0_0_
from
dept dept0_
where
dept0_.id=?
//由于数据库表中没有id=1的数据,所以拿到的记录是从id=4开始。也就是从第三条到第六条
Staff [id=4, name=qqq3, dept=oneToMany.Dept@2bf11e9f]
Staff [id=5, name=qqq4, dept=oneToMany.Dept@2bf11e9f]
Staff [id=6, name=qqq5, dept=oneToMany.Dept@2bf11e9f]

  

            1.3.4、支持连接查询

                支持7种连接写法。

                1.3.4.1、内连接 inner join  可以省略inner,直接join

         //注意,hql操作的是POJO,而不是表中字段,所以s.dept这里不能写成Dept或者dept,
//不用写ON后面的连接条件,因为hibernate映射文件我们已经全部写好了。
String hql = "from Dept d inner join d.staffSet";
Query hqlQuery = session.createQuery(hql);
//这里的泛型不能是Staff了。结合了两张表,集合中存放的是Object[],数组中存放的是Staff和Dept实体
List<Object[]> list = hqlQuery.list(); //集合中存放的是id,name数组。。
Object[] o = list.get(0);
System.out.println(o);
//注意:其中Dept和Staff中都没有对方实体的引用。因为这个是左外连接,生成了新的表。
System.out.println(((Dept)o[0]).getName());//获得Dept实体的name
System.out.println(((Staff)o[1]).getName());//或者Staff的name //结果
//左外连接的语句,并且为我们加上了ON之后的语句
Hibernate:
select
dept0_.id as id0_0_,
staffset1_.id as id1_1_,
dept0_.name as name0_0_,
staffset1_.name as name1_1_,
staffset1_.deptId as deptId1_1_
from
dept dept0_
inner join
staff staffset1_
on dept0_.id=staffset1_.deptId
//这个是list中第一个Object[] 不用看他的格式,只要知道他有代表着Dept和Staff实体
[Ljava.lang.Object;@44eef74f
1部门
qqq1

                        

                1.3.4.2、迫切内连接 inner join fetch

                    内连接返回的list中是Object[],而迫切内连接返回的list中是POJO类对象

         //注意,hql操作的是POJO,而不是表中字段,所以s.dept这里不能写成Dept或者dept,
//不用写ON后面的连接条件,因为hibernate映射文件我们已经全部写好了。
String hql = "from Dept d inner join fetch d.staffSet";
Query hqlQuery = session.createQuery(hql);
//使用的是迫切内连接,其list中放的就是Dept对象了,注意并没有包含staffSet。放的是from后面跟的POJO,如果是Staff。那么这里就放的Staff。
//所以自己重写了toString方法的人这里会报错,
List list = hqlQuery.list(); //集合中存放的是Dept。
System.out.println(list); //结果
Hibernate:
select
dept0_.id as id0_0_,
staffset1_.id as id1_1_,
dept0_.name as name0_0_,
staffset1_.name as name1_1_,
staffset1_.deptId as deptId1_1_,
staffset1_.deptId as deptId0_0__,
staffset1_.id as id0__
from
dept dept0_
inner join
staff staffset1_
on dept0_.id=staffset1_.deptId
//返回那么多相同的原因是内连接,Staff中有9条记录,则部门这边也会显示9条,所以这里重复了9次。可以是用DISTINCT关键字去除重复的记录
[Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门], Dept [id=2, name=1部门]]

                要想得到不重复的记录,那么就将hql改为"select distinct d from Dept d inner join fetch d.staffSet";

                1.3.4.3、隐式内连接 不写任何关键字,完成表连接

                    其实就是通过where连接两张表。很简单。

         //隐式内连接,其实就是最普通的通过where来连接两张表,如何看了MySQL的表查询操作,
//这个应该很简单,但是这里只能通过多方找一方,因为一方存放的是集合,就不能向下面这样赋值
String hql = "from Staff s where s.dept.name = ?";
Query hqlQuery = session.createQuery(hql);
hqlQuery.setParameter(0, "1部门"); List list = hqlQuery.list(); //集合中存放的是Dept。
System.out.println(list);
//结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_ cross
join
dept dept1_
where
staff0_.deptId=dept1_.id
and dept1_.name=?
[Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]

                1.3.4.4、左外连接,left outer join,可以省略outer,直接left join

         //左外连接,自己脑袋里想一下在左外连接的时候,表会是什么样子。通过前面看到的内连接
//和迫切内连接就应该知道这里左外连接list中存放的是什么,就是Object[]
String hql = "from Staff s left outer join s.dept";
Query hqlQuery = session.createQuery(hql); List<Object[]> list = hqlQuery.list();
Object[] object = list.get(0);
System.out.println(((Staff)object[0]).getName());
System.out.println(((Dept)object[1]).getName()); //结果
Hibernate:
select
staff0_.id as id1_0_,
dept1_.id as id0_1_,
staff0_.name as name1_0_,
staff0_.deptId as deptId1_0_,
dept1_.name as name0_1_
from
staff staff0_
left outer join
dept dept1_
on staff0_.deptId=dept1_.id
qqq1
1部门

                1.3.4.5、迫切左外连接, left outer join fetch

                  一样的区别,就是list中存放的是POJO对象了

         //迫切左外连接,就是list中存放的是POJO对象。在这里存放的是Staff。
String hql = "from Staff s left outer join fetch s.dept";
Query hqlQuery = session.createQuery(hql); List list = hqlQuery.list();
System.out.println(list); //结果
Hibernate:
select
staff0_.id as id1_0_,
dept1_.id as id0_1_,
staff0_.name as name1_0_,
staff0_.deptId as deptId1_0_,
dept1_.name as name0_1_
from
staff staff0_
left outer join
dept dept1_
on staff0_.deptId=dept1_.id
[Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5],
Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]

                1.3.4.6、右外连接:right outer join

                  知道左外连接,右外连接也就会了。

         //右外连接,就是list中存放的是Object[]
String hql = "from Staff s right outer join s.dept";
Query hqlQuery = session.createQuery(hql); List<Object[]> list = hqlQuery.list();
System.out.println(list); //结果
Hibernate:
select
staff0_.id as id1_0_,
dept1_.id as id0_1_,
staff0_.name as name1_0_,
staff0_.deptId as deptId1_0_,
dept1_.name as name0_1_
from
staff staff0_
right outer join
dept dept1_
on staff0_.deptId=dept1_.id
[[Ljava.lang.Object;@11e04129, [Ljava.lang.Object;@19d5f3ea, [Ljava.lang.Object;@2d8094e6, [Ljava.lang.Object;@54af9f60, [Ljava.lang.Object;@5608830f, [Ljava.lang.Object;@48d479e9, [Ljava.lang.Object;@758fd559, [Ljava.lang.Object;@3600025b, [Ljava.lang.Object;@3a9ac00f]

                1.3.4.7、交叉连接,会产生笛卡尔积。

                  什么是笛卡尔积?将两张表连接起来,比如一张表中有3条记录,另一张表中也有3条记录,那么连接之后,就会出现9条数据,其中就有一些重复的数据,拿实例说话,班级和学生,有三个学生A,B,C,有两个班级E,F,连接起来后,就会出现笛卡尔积,6条数据,其中会出现这样的数据,A,E 、A,F、B,E、B,F、C,E、C,F, A,B,C就重复出现了,即在E班级,又在F班级,这样就不合理。这就是所说的笛卡尔积。

                  由于dept中就一条记录,无法展示出笛卡尔积,所以手动增加一条dept的记录。然后在进行交叉连接。就会出现笛卡尔积,

         //直接将两张表简单相连,出现笛卡尔积,因为从结果中可以看到,list集合中有18个数组,说明有18条记录
String hql = "from Staff,Dept";
Query hqlQuery = session.createQuery(hql); List list = hqlQuery.list();
System.out.println(list); //结果
Hibernate:
select
staff0_.id as id1_0_,
dept1_.id as id0_1_,
staff0_.name as name1_0_,
staff0_.deptId as deptId1_0_,
dept1_.name as name0_1_
from
staff staff0_ cross
join
dept dept1_
//18个数组
[[Ljava.lang.Object;@42064d82, [Ljava.lang.Object;@2bcab3ab, [Ljava.lang.Object;@8d9b603, [Ljava.lang.Object;@d3c837f, [Ljava.lang.Object;@7fdd0da2, [Ljava.lang.Object;@9aa4843, [Ljava.lang.Object;@a6e2baa, [Ljava.lang.Object;@46f4ab3f, [Ljava.lang.Object;@6916d97d, [Ljava.lang.Object;@5b20d371, [Ljava.lang.Object;@4819ce74, [Ljava.lang.Object;@164146a7, [Ljava.lang.Object;@1785895b, [Ljava.lang.Object;@3ffcc16d, [Ljava.lang.Object;@6afefbec, [Ljava.lang.Object;@a4d79d5, [Ljava.lang.Object;@6479943b, [Ljava.lang.Object;@69f2e105]

                

               注意:上面的连接中很多是使用一个引用就代表了相对应的表,比如" from Dept d inner join d.staffSet " d.staffSet就好像代表了Staff的这张表,实际上就是代表了Staff这张表,这样理解,from Dept 就从Dept表中找出了所有记录,就打比方,找到了Dept表中的2部门,在2部门中有多少staff呢,可以全部找出来,在我们所说的环境下,正好就staff就全部在该部门中,那么就找到了Staff表中的所有staff,也就是相当于是Staff这张表了,就算2部门没有包括所有的staff,那么还有其他部门,肯定包括了剩下的staff,也就是说,不管怎么样,度能把staff全部找到,所以d.staffSet就相当于Staff表了。以此类推,其他hql语句中的这里也是这样理解的。

             1.3.5、支持分组查询,允许使用HAVING 和 GROUP BY 关键字

                

         //s.dept.id 就相当于操作Staff表中的deptId。看发送的sql语句就能知道。
//原因是Staff这个类中并没有deptId表字段属性,但是有dept的引用变量,其dept的id
//也就是Staff中的deptId值,只是中间转换了一步,也不是很难理解。
String hql = "from Staff s group by s.dept.id";
Query hqlQuery = session.createQuery(hql);
List list = hqlQuery.list();
System.out.println(list); //结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
group by
staff0_.deptId
//分组后显示的就是第一个值。由于数据问题,9个staff度是在一个部门,所以通过部门分组,就只能得到一个分组。
[Staff [id=2, name=qqq1]]

             1.3.6、提供内置聚集函数,如SUM(),MIN(),MAX()等

这个例子中不好使用这几个函数。。。所以这里不演示了,很简单。hql和sql差不太多。

             1.3.7、能够调用用户定义的SQL函数或标准的SQL函数

这个跟上面的一样,SQL中函数有很多。也就是说hql能够使用sql中的函数

             1.3.8、支持子查询        

         //子查询操作,实际意义:Staff表中的staff所在的部门编号,跟Dept中所有的部门编号有对应的,就将其staff取出。
String hql = "from Staff s where s.dept.id IN (select id from Dept)";
Query hqlQuery = session.createQuery(hql);
List list = hqlQuery.list();
System.out.println(list);
//结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
where
staff0_.deptId in (
select
dept1_.id
from
dept dept1_
)
[Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]

            1.3.9、条件查询,给hql中动态设置参数的两种方式

                    方式一:from Staff where id = ? 使用?代替所需要填入的值,在下面设置值时则从0开始算起,第一个?是处于0的位置,如果有两个?号,则使用0,1索引号来插入值。

         String hql = "from Staff where id = ?";
Query hqlQuery = session.createQuery(hql); hqlQuery.setParameter(0, 4); Staff staff = (Staff) hqlQuery.uniqueResult();
System.out.println(staff.toString()); //结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
where
staff0_.id=?
Hibernate:
select
dept0_.id as id0_0_,
dept0_.name as name0_0_
from
dept dept0_
where
dept0_.id=?
Staff [id=4, name=qqq3, dept=oneToMany.Dept@f1cb8ac]

                    方式二:from Staff where id = :id  使用":id"这个名字来表示插入值的名称,在下面则不用索引号来确定插入值的位置,直接是使用这个别称

         String hql = "from Staff where id = :id";
Query hqlQuery = session.createQuery(hql); hqlQuery.setParameter("id", 4); Staff staff = (Staff) hqlQuery.uniqueResult();
System.out.println(staff.toString()); //结果
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
where
staff0_.id=?
Hibernate:
select
dept0_.id as id0_0_,
dept0_.name as name0_0_
from
dept dept0_
where
dept0_.id=?
Staff [id=4, name=qqq3, dept=oneToMany.Dept@1539b7a6]

                    注意,在位置上不仅仅可以插入值,还可以插入一个对象。例如

         String hql = "from Staff s where s.dept = ?";
Query hqlQuery = session.createQuery(hql);
Dept dept = (Dept)session.get(Dept.class, 2);
hqlQuery.setEntity(0, dept); //给相应位置添加一个dept对象
List list = hqlQuery.list();
System.out.println(list); //结果
//这个是查询dept发送的sql语句
Hibernate:
select
dept0_.id as id0_0_,
dept0_.name as name0_0_
from
dept dept0_
where
dept0_.id=?
//这个是我们写的hql发送的sql语句
Hibernate:
select
staff0_.id as id1_,
staff0_.name as name1_,
staff0_.deptId as deptId1_
from
staff staff0_
where
staff0_.deptId=?
[Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]

                    这两种方式度可以,不过在参数比较多的情况下,建议使用别名,那样更加清楚,不易出错,在少量参数时可以使用索引。

  

      1.4、QBC检索方式

          QBC:Query By Criteria,是一种更加面向对象的查询语言,提供的一系列QBC API来检索对象。

          HQL所能做的事情,使用QBC也大多能做用,这个通过实例来看看QBC是如何使用的。  

           步骤:

             1>获得session

             2>session.createCriteria(Obejct.class); 创建criteria对象

             3>使用criteria的API方法进行条件的增加。add(Restrictions.eq(属性名,值))

             4>执行查询

                  list():返回一个集合列表,有可能集合中装的是数组,有可能是POJO对象。

                  uniqueResult():返回一个查询结果,在已知查询结果只有一个或者0个时,使用是没有问题的,如果返回结果有多个,那么就会报异常

          例子一:使用QBC来对Staff进行查询

         //使用QBC,更加面向对象,不用写sql语句。要查询什么,就直接将其类.class当作参数就能查询出来
Criteria QBCCriteria = session.createCriteria(Staff.class);
List<Staff> staffList = QBCCriteria.list();
for(Staff staff : staffList){
System.out.println(staff.toString());
}
//结果
Hibernate:
select
this_.id as id1_0_,
this_.name as name1_0_,
this_.deptId as deptId1_0_
from
staff this_
Staff [id=2, name=qqq1]
Staff [id=3, name=qqq2]
Staff [id=4, name=qqq3]
Staff [id=5, name=qqq4]
Staff [id=6, name=qqq5]
Staff [id=7, name=qqq6]
Staff [id=8, name=qqq7]
Staff [id=9, name=qqq8]
Staff [id=10, name=qqq9]

          例子二:使用QBC来对Staff进行条件查询

         //使用QBC,对Staff进行查询
Criteria QBCCriteria = session.createCriteria(Staff.class);
//add()添加条件,通过Restrictions(字段名,值),由于确定是1行记录,所以直接用uniqueResult()
Staff staff = (Staff) QBCCriteria.add(Restrictions.eq("id",3)).uniqueResult(); System.out.println(staff.toString()); //结果
Hibernate:
select
this_.id as id1_0_,
this_.name as name1_0_,
this_.deptId as deptId1_0_
from
staff this_
where
this_.id=?
Staff [id=3, name=qqq2]

          例子三:QBC也能进行连接查询

         // from Staff inner join dept d ON 后面是hibernate自动帮我们填写;
Criteria criteria = session.createCriteria(Staff.class);
//createAlias默认是内连接,可以不用写。可以为dept表取别名,也可以不取。
criteria.createAlias("dept", "d", Criteria.INNER_JOIN);
List list = criteria.list();
System.out.println(list); //结果
Hibernate:
select
this_.id as id1_1_,
this_.name as name1_1_,
this_.deptId as deptId1_1_,
d1_.id as id0_0_,
d1_.name as name0_0_
from
staff this_
inner join
dept d1_
on this_.deptId=d1_.id
[oneToMany.Staff@6a155d66, oneToMany.Staff@55a7e5ae, oneToMany.Staff@1d82e71, oneToMany.Staff@17d0fda9, oneToMany.Staff@19bd6e76, oneToMany.Staff@639f122d, oneToMany.Staff@60627b73, oneToMany.Staff@6196ec74, oneToMany.Staff@7b7de5b9]

          给一张表来看看qbc增加的条件查询语句。

                

          重点有一个离线Criteria对象的用法。

            1、在web层封装查询条件到离线Criteria对象中,将其DetachedCriteria对象绑定到Thread上。

            2、到dao层,就能通过Thread拿到该离线Criteria对象,然后创建session。将session给DetachedCriteria,就能够执行查询

            代码:

             WEB层

              DetachedCriteria detachedCriteria =DetachedCriteria.forClass(Customer.class);

              detachedCriteria.add(Restrictions.eq("name", "kitty"));

             DAO层

              Session session = HibernateUtils.openSession();

                  Transaction transaction = session.beginTransaction();

                // 将离线查询对象 关联到Session

               Criteria criteria = detachedCriteria.getExecutableCriteria(session);

               Customer customer = (Customer) criteria.uniqueResult();

                

    

      1.5、本地SQL检索方式

          使用标准的SQL语句来编写。

          步骤:

            1>获得session

            2>编写sql语句

            3>session.createSQLQuery(sql);获取SQLQuey对象

            4>给sql语句设置参数。

            5>执行查询

                  list():返回一个集合列表,集合中装的是Object[]。

                  返回实体类对象集合,如果与实体类进行了绑定,也就是使用了addEntity(xxx.class)。

          例子一:查询Staff的所有记录

         //使用的就是数据库表名了。
SQLQuery SQLquery = session.createSQLQuery("select * from staff");
//返回的是一个List<Object[]> 其中如果使用的SQL的话,
//后面不能够通过获得数组然后在转换为对象。只有通过addEntity。来绑定实体。
List list = SQLquery.list();
System.out.println(list); //结果
Hibernate:
select
*
from
staff
[[Ljava.lang.Object;@2c8938a8, [Ljava.lang.Object;@64e6b46f, [Ljava.lang.Object;@66501729, [Ljava.lang.Object;@1420b939, [Ljava.lang.Object;@70605781, [Ljava.lang.Object;@45110fca, [Ljava.lang.Object;@6323ba32, [Ljava.lang.Object;@3e955b77, [Ljava.lang.Object;@3fa801ba]

          例子二:查询Staff的所有记录,并且绑定实体。 addEntity。

         //使用的就是数据库表名了。
SQLQuery SQLquery = session.createSQLQuery("select * from staff");
//返回的是一个List<Object[]> 只有通过addEntity。来绑定实体。
List<Staff> list = SQLquery.addEntity(Staff.class).list();
System.out.println(list.get(0).getName()); //结果
Hibernate:
select
*
from
staff
qqq1

二、总结

      以上就是我们说的5种检索,其中说的重点就是hql的用法,上面的例子全部写完了差不多就对hql有一定的了解。记住hql是对pojo类进行操作,而不是对数据库中的表。在使用连接查询时,可以使用QBC,因为更简单,只需要用createAlias()就能使用任何的连接。一般在开发中sql语句都会提取出来放到hbm中,例如

      

        在hbm映射文件 (也可以用注解配置)

             <!-- 这里可以定义命名查询 -->

           <!--        定义 HQL 语句 <query name=""></query> -->

          <!--        定义 SQL 语句 <sql-query name=""></sql-query> -->

            <query name="findCustomerByName">

          <![CDATA[from Customer where name = ?]]>

          </query>

            * 为hql语句 起了一个名字

        程序代码:

            //相当于把sql语句分离开来了。方便维护

            Query query = session.getNamedQuery("findCustomerByName");

             query.setParameter(0, "tom");

          Customer customer = (Customer) query.uniqueResult();

hibernate(七) hibernate中查询方式详解的更多相关文章

  1. Hibernate学习(七)———— hibernate中查询方式详解

    序言 之前对hibernate中的查询总是搞混淆,不明白里面具体有哪些东西.就是因为缺少总结.在看这篇文章之前,你应该知道的是数据库的一些查询操作,多表查询等 --WH 一.hibernate中的5种 ...

  2. hibernate集合映射inverse和cascade详解

    hibernate集合映射inverse和cascade详解   1.到底在哪用cascade="..."? cascade属性并不是多对多关系一定要用的,有了它只是让我们在插入或 ...

  3. hibernate的三种查询方式

    hibernate的三种查询方式 目录 hibernate的三种查询方式 1.HQL查询 1.1.SQL概述 1.2.实体查询 1.3.带where的查询 1.3.属性查询 1.4.实体的更新和删除 ...

  4. JAVA中的四种JSON解析方式详解

    JAVA中的四种JSON解析方式详解 我们在日常开发中少不了和JSON数据打交道,那么我们来看看JAVA中常用的JSON解析方式. 1.JSON官方 脱离框架使用 2.GSON 3.FastJSON ...

  5. oracle中imp命令详解 .

    转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...

  6. Spring事务Transaction配置的五种注入方式详解

    Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...

  7. Django框架 之 ORM查询操作详解

    Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...

  8. MySQL查询缓存详解(总结)

    MySQL查询缓存详解(总结) 一.总结 一句话总结: mysql查询缓存还是可以用用试一试,但是更推荐分布式,比如redis/memcache之流,将数据库中查询的数据和查询语句以键值对的方式存进分 ...

  9. MongoDB各种查询操作详解

    这篇文章主要介绍了MongoDB各种查询操作详解,包括比较查询.关联查询.数组查询等,需要的朋友可以参考下   一.find操作 MongoDB中使用find来进行查询,通过指定find的第一个参数可 ...

随机推荐

  1. Angular概念纵览

    Conceptual Overview Template(模板): HTML with additional markup (就是增加了新的标记的HTML) Directive(指令): extend ...

  2. PHP如何将中文转换为拼音

    用来得到中文的首字母: 这个是将中文转换为拼音的类:charset <?php/*** 汉字转化为拼音,拼音转化为汉字**/ class charset{private $_code=array ...

  3. 在WPF的WebBrowser控件中屏蔽脚本错误的提示

    在WPF中使用WebBrowser控件显示网页时,经常会报脚本错误的提示,如何屏蔽掉这些错误提示呢.方法是定义如下方法: public void SuppressScriptErrors(WebBro ...

  4. Cannot refer to an instance field pageTitle while explicitly invoking a cons

    当下面这样时在第7行会提示:Cannot refer to an instance field pageTitle while explicitly invoking a cons public cl ...

  5. 20145301&20145321&20145335实验四

    20145301&20145321&20145335实验四 这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验四

  6. 单用户模式下修改root密码

    1.重启或者开机时,在倒数3秒的界面按下任意键. 2.该界面有如下提示(e 编辑 a 更改内核选项 c 命令行  b 启动),所以我们按下"e"编辑. 3.上下键选中第二行再按下& ...

  7. [Linux-shell] AWK

    Go to the first, previous, next, last section, table of contents. Printing Output One of the most co ...

  8. Mysql 之旅开始啦

    本来是打算以后从事oracle 的DBA 的,结果面试了mysql的dba,总的来说学习到的oracle 知识还是在面试中很有用的,毕竟都是想通的.最近又不好好学习了,为了鼓励自己多学习mysql,以 ...

  9. sphinx教程

    http://www.php100.com/html/it/focus/2013/0916/6188.html### 以上一篇的email数据表为例: 数据结构: 01.CREATE TABLE em ...

  10. 蛙蛙推荐:WEB安全入门

    信息安全基础 信息安全目标 真实性:对信息的来源进行判断,能对伪造来源的信息予以鉴别, 就是身份认证. 保密性:保证机密信息不被窃听,盗取,或窃听者不能了解信息的真实含义. 完整性:保证数据的一致性, ...