6.4.5  左外连接

左外连接(Left Outer Join)查询出左表对应的复合条件的所有记录,如查询李晓梅同学的选课信息。下面是类HQLLeftOuterJoinQuery的源代码。

package hibernate.ch06;

import hibernate.HibernateSessionFactory;

import java.util.Iterator;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.Session;

public class HQLLeftOuterJoinQuery {

      public static void main(String[] args) {

            Session session=HibernateSessionFactory.currentSession();

      

            //HQL查询语句

            String hql="from Student s left join s.course c where s.sname='李晓梅'";

       

            Query query=session.createQuery(hql);         //创建查询

       

            List list=query.list();                          //执行查询

            Iterator it=list.iterator();

       

            while(it.hasNext()){

                  Object[] obj=(Object[])it.next();

                  Student stu=(Student)obj[0];

                  Course course=(Course)obj[1];

                  System.out.println("*********学生信息及其选课信息******************");

                  if(course!=null){

                   System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t"+

                                "课程:"+course.getCname());

                   }else{

                         System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t");

                   };

            }

      }

}

如果只用单表查询,只能从student表中查询出李晓梅的个人信息,而无法知道她的选课信息,因为选课信息存储在中间表sc中。HQL语句from Student s left join s.course c where s.sname='李晓梅'检索出了李晓梅的选课信息。

*     在HQL中使用left outer join关键字进行左外连接,outer关键字可以省略。

*     s.course是Student对象中的一个属性,用来存储Student对象的选课信息。在执行查询时,将根据Student.hbm.xml中的配置生成SQL语句,并检索信息。

*     查询的结果返回一个Object[]数组,数组的第0个元素是Student对象,第1个元素是与Object[0]中对应的学生所选课的Course对象。

HQLLeftOuterJoinQuery类在执行过程中生成的左外连接的SQL语句如下。

Hibernate:

    select

         student0_.id as id1_0_,

         course2_.id as id4_1_,

         student0_.Sno as Sno1_0_,

         student0_.Sname as Sname1_0_,

         student0_.Sdept as Sdept1_0_,

         student0_.Sage as Sage1_0_,

         student0_.Ssex as Ssex1_0_,

         student0_.Saddress as Saddress1_0_,

         course2_.Cno as Cno4_1_,

         course2_.Cname as Cname4_1_,

         course2_.Ccredit as Ccredit4_1_

    from

         joblog.student student0_

    left outer join

         sc course1_

              on student0_.id=course1_.sno

    left outer join

         joblog.course course2_

              on course1_.cno=course2_.id

    where

         student0_.Sname='李晓梅'

Hibernate:

    select

         course0_.sno as sno1_,

         course0_.cno as cno1_,

         course1_.id as id4_0_,

         course1_.Cno as Cno4_0_,

         course1_.Cname as Cname4_0_,

         course1_.Ccredit as Ccredit4_0_

    from

         sc course0_

  left outer join

         joblog.course course1_

               on course0_.cno=course1_.id

    where

         course0_.sno=?

程序的查询结果如下。

*********学生信息及其选课信息******************

20040001    李晓梅    课程:数据库

*********学生信息及其选课信息******************

20040001    李晓梅    课程:操作系统

使用如下语句将只返回Student对象。

select s from Student s left join s.course c where s.sname='李晓梅'

如下是只返回Student对象的部分代码。

        Session session=HibernateSessionFactory.currentSession();

       

        //HQL查询语句

        String hql="select s from Student s left join s.course c where s.sname='李晓梅'";

        Query query=session.createQuery(hql);             //创建查询

       

        List list=query.list();                             //执行查询

       

        Iterator it=list.iterator();

       

        while(it.hasNext()){

              Student stu=(Student)it.next();

              System.out.println("*********学生信息及其选课信息******************");

              System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t");

        }

6.4.6  左外抓取连接

左外抓取连接指定在Hibernate检索数据时,采用抓取的方式,直接将数据加载到与Student对象关联的course属性中。下面是左外抓取连接的程序。

        //HQL查询语句

        String hql="select s from Student s left join fetch s.course c where s.sname='李晓梅'";

        Query query=session.createQuery(hql);             //创建查询

       

        List list=query.list();                             //执行查询

       

        Iterator it=list.iterator();

       

        while(it.hasNext()){

               Student stu=(Student)it.next();

               System.out.println("*********学生信息及其选课信息******************");

               System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t");

        }

*     左外抓取连接使用left join fetch关键字。

*     与左外连接不同的是:左外抓取连接query.list()返回的集合中存放Student对象的引用,与之相关联的选课信息存放在course属性中。

6.4.7  右外连接

HQL中使用关键字right outer join右外连接,outer关键字可以省略。右外连接与左外连接类似,不再赘述。

6.4.8  内连接

内连接(Inner Join)是指两个表中指定的关键字相等的值才会出现在结果集中的一种查询方式。HQL中使用关键字inner join进行内连接,下面是使用内连接的程序。

        Session session=HibernateSessionFactory.currentSession()             //创建Session

       

        String hql="from Student s inner join s.course c";                    //HQL查询语句

        Query query=session.createQuery(hql);                                    //创建查询

        List list=query.list();                                                    //执行查询

       

        Iterator it=list.iterator();

            

        while(it.hasNext()){

               Object[] obj=(Object[])it.next();

               Student stu=(Student)obj[0];

               Course course=(Course)obj[1];

               System.out.println("*********学生信息及其选课信息******************");

               System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t"+"课程:"+course. getCname());

        }

*     HQL中使用inner join进行内连接,内连接只关联并检索那些选了课的学生信息及其选课信息,没有选课的学生不在检索结果中。

*     可以使用select s from Student s inner join s.course c只返回Student对象。

6.4.9  抓取内连接

抓取内连接与内连接不同之处在于其对象的内存状态不一样。HQL中使用inner join fetch进行抓取内连接,如下程序所示。

        Session session=HibernateSessionFactory.currentSession();            //创建Session

       

        String hql="select s from Student s inner join fetch s.course c";                //HQL语句

        Query query=session.createQuery(hql);                                    //创建查询

       

        List list=query.list();                                                    //执行查询

       

        Iterator it=list.iterator();

       

        while(it.hasNext()){

        Student stu=(Student)it.next();

        System.out.println("*********学生信息及其选课信息******************");

        System.out.println(stu.getSno()+"\t"+stu.getSname()+"\t");

    }

*     内抓取连接使用inner join fech关键字。

*     它与内连接的区别是返回检索的list中存放的是Student对象的引用,与之相关联的选课信息存放在course属性中。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐