连接查询

 

连接查询:
   关系型数据库之所以强大,其中一个原因就是可以统一使用表来管理同类数据信息,并且可以在相关数据之间建立关系。作为支持关系型数据库的 SQL 语句来说,自然要对全面发挥这种强大功能提供支持,这个支持就是连接查询。同样作为一种关系型数据库的持久层框架, Hibernate 也对连接查询提供了丰富的支持,在 Hibernate 中通过 HQL QBC 两种查询方式都可以支持连接查询。下面这一部分我们将通过这两种查询技术,来详细讨论有关 Hibernate 对连接查询支持的各个细节。在讲解连接查询之前,我们先来回忆一下在第一部分中讲解的有关实体关联关系的映射,在实体的配置文件中可以通过配置集合元素来指定对关联实体的映射以及检索策略。(请参考第一部分相关内容)因此我们可以在实体映射配置文件中,指定关联实体检索策略,对关联实体的检索策略可以指定为“延迟检索”,“立即检索”,“迫切左外连接检索”,如下所示对与 Customer 实体关联的 Order 实体设置延迟加载: <set name=”orders” inverse=”true” lazy=”true”>, 这种在实体映射配置文件中设定的检索策略,称为默认检索策略,但是这种默认检索策略是可以被覆盖的,那就是在程序代码当中可以动态指定各种迫切检索策略来覆盖默认检索策略。
1、    迫切左外连接查询和左外连接查询:
我们看以下代码,这段代码将覆盖映射文件中的检索策略,显示指定采用迫切左外连接查询。
 
HQL 查询方式:
Query query=session.createQuery(“from Customer c left join fetch c.orders o where c.name       like ‘zhao%’ ”);
List list=query.list();
for(int i=0;i<list.size();i++){
 Customer customer=(Customer)list.get(i);
}
//QBC 检索方式:
List list=session.createCriteria(Customer.class).setFetchMode(“orders”, FetchMode.EAGER )
        .add(Expression.like(“name”,”zhao%”,MatchMode.START).list();
for(int i=0;i<list.size();i++){
 Customer customer=(Customer)list.get(i);
}
我们看到在 HQL 以及 QBC 查询中分别通过 left join fetch FetchMode.EAGER 来指定采用迫切左外连接检索策略,当采用了迫切左外连接检索策略时,当进行检索时即执行查询的 list() 方法时,将会立即初始化用来容纳关联实体的集合对象元素,如果在实体映射配置文件中对关联实体设置了延迟加载,那么此时将会忽略延迟加载设置,而采用迫切左外连接策略,并且立即用关联实体对象填充集合对象元素,即使用 Order 对象填充 Customer 对象的 orders 集合。因此这种检索策略会马上创建关联实体对象,此时我想你一定会想到这种检索策略会同时检索出 Customer Order 实体对象对应的数据,并且分别创建这两个对象。恭喜你答对了,因此上面代码会生成类似如下的 SQL 语句:
Select * from customer c left join order o on c.id=o.id where c.name like ‘zhao%’;
如果我们忽略了 fetch 关键字,就变成了左外连接查询,如下面代码:
Query query=session.createQuery(“from Customer c left join c.orders o where c.name       like ‘zhao%’ ”);
List list=query.list();
for(int i=0;i<list.size();i++){
 Object[] objs=(Object[])list.get(i);
 Customer customer=(Customer) objs[0];
 Order order=(Order)objs[1];
}
我们可以看到采用左外连接查询返回的结果集中包含的是对象数组,对象数组中的每个元素存放了一对相互关联的 Customer 对象和 Order 对象,而迫切左外连接会返回 Customer 对象,与 Customer 对象相关联的 Order 对象存放在 Customer 对象的集合元素对象中,这就是迫切左外连接和左外连接查询的其中一个区别(这两种检索生成的 SQL 语句是一样的),另一个区别是当使用左外连接时,对关联对象的检索会依照实体映射配置文件所指定的策略,而不会像迫切左外连接那样忽略它,比如此时对 Customer 对象关联的 Order 对象采用延迟加载,那么左外连接检索也会使用延迟加载机制检索 Order 对象。
2 、内连接,迫切内连接以及隐式内连接:
  若采用迫切内连接通过一下代码可以实现:
Query query=session.createQuery(“from Customer c inner join fetch c.orders o where c.name       like ‘zhao%’ ”);
List list=query.list();
for(int i=0;i<list.size();i++){
 Customer customer=(Customer)list.get(i);
}
这段代码将会采用迫切内连接检索,对集合元素的检索策略以及返回结果集中的对象类型都采用与迫切左外连接一样的方式,我这里就不再赘述,另外 QBC 查询不支持迫切内连接检索。
如果去掉 fetch 就是内连接检索,如下面代码:
Query query=session.createQuery(“from Customer c inner join c.orders o where c.name       like ‘zhao%’ ”);
List list=query.list();
for(int i=0;i<list.size();i++){
 Object[] objs=(Object[])list.get(i);
 Customer customer=(Customer) objs[0];
 Order order=(Order)objs[1];
}
内连接检索,对集合元素的检索策略以及返回结果集中的对象类型都采用与左外连接一样的方式, QBC 查询也同样支持内连接检索,如下代码:
List list=session.createCriteria(Customer.class)
.add(Expression.like(“name”,”zhao%”,MatchMode.START))
.createCriteria(“orders”)
.add(Expression.like(“ordernumber”,”T”,MatchMode.START)).list();
      上面代码等价于如下的 HQL 语句:
      Select c from Customer c join c.orders o where c.name like ‘zhao%’ and o.ordernummber like ‘T%’; 因此可以采用下面的方式访问结果集:
for(int i=0;i<list.size();i++){
 Customer customer=(Customer)list.get(i);
}
      由此可见,采用内连接查询时 ,HQL QBC 查询有不同的默认行为, HQL 会检索出成对的 Customer Order 对象,而 QBC 仅会检索出 Customer 对象。如果 QBC 查询想检索出成对的 Customer Order 对象,可以采用如下代码:
List list=session.createCriteria(Customer.class)
.createAlias(“orders”,”o”)
.add(Expression.like(“this.name”,”zhao%”,MatchMode.START))
.add(Expression.like(“ordernumber”,”T”,MatchMode.START))
.returnMap()
.list();
for(int i=0;i<list.size();i++){
   Map map=(Map)list.get(i);
 Customer customer=(Customer)map.get(“this”);
 Order order=(Order)map.get(“o”);
}
    “o” ”this” 分别是 orders 集合和 Customer 对象的别名。
    HQL 查询中,还有一种查询成为隐式内连接,我们看下面的 HQL 语句,
      From Order o where o.customer.name like ’ zhao% ’; 这个语句通过 o.customer.name 访问与 Order 对象关联的 Customer 对象的 name 属性,尽管没有使用 join 关键字,其实隐式指定了采用内连接检索,它和下面这条 HQL 语句等价:
From Order o join o.customer c where c.name like ‘zhao%’;
隐式内连接只适用于多对一和一对一关联,不适用于一对多和多对多关联,另外 QBC 查询不支持隐式内连接检索。
3 、右外连接检索:
由于 fetch 关键字只能应用于 innner join left join ,因此对于右外连接检索而言,就不存在所谓的迫切右外连接查询了,使用右外连接见如下代码:
Query query=session.createQuery(“from Customer c right join c.orders o where c.name       like ‘zhao%’ ”);
List list=query.list();
for(int i=0;i<list.size();i++){
 Object[] objs=(Object[])list.get(i);
 Customer customer=(Customer) objs[0];
 Order order=(Order)objs[1];
}
      右外连接检索 , 对集合元素的检索策略以及返回结果集中的对象类型都采用与左外连接一样的方式。
4 、交叉连接:
  对于不存在关联关系的两个实体对象,不能使用内连接查询,也不能使用外连接查询,此时可以使用具有 SQL 风格的交叉连接,如下面代码:
Select c.ID,c.name,c.age,o.ID,o.ordernumber,o.customer_ID
From Customer c,Order o;
这个 HQL 语句将会执行交叉连接检索,而且将会返回 customer 表和 order 表的笛卡儿积关联结果。
5 、连接查询运行时检索策略总结:
①、如果在 HQL QBC 查询中没有指定检索策略,那么将会使用映射配置为件中指定的检索策略,但是这里有一个例外,那就是 HQL 检索总是会忽略实体映射配置文件中对关联实体指定的迫切左外连接检索策略,也就是说如果配置文件中指定对关联实体采用迫切走外连接检索,但是在 HQL 查询语句中没有指定这种检索策略,此时 Hibernate 将会忽略这种检索策略,而依然采用立即检索。因此如果希望采用迫切左外连接检索,就必须在 HQL 语句中明确指定。
②、如果在 HQL 或者 QBC 检索中明确指定了检索策略,就会覆盖配置文件中的默认检索策略,在 HQL 查询中通过 left join fetch inner join fetch 来明确指定检索策略,在 QBC 查询中通过 FetchMode.DEFAULT,FetchMode.EAGER,FetchMode.LAZY 来明确指定检索策略。
①、             目前的 Hibernate 的各种版本中,只允许在一个查询中迫切左外连接检索一个集合,即只允许存在一个一对多关联,但是允许存在多个一对一和多对多关联。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值