hibernate 一對多和多對一查詢

一、一對多
以班級Classes和學生Student爲例:

回憶sql語句:

//內鏈接,兩種方式效果一樣,查詢的是兩邊都有的數據
SELECT c.*,s.* FROM classes c,student s WHERE s.cid=c.cid;

SELECT c.cname,s.sname FROM classes c INNER JOIN student s ON s.cid=c.cid;

//左外連接,在內鏈接基礎上,左邊表有而右邊表沒有,兩種方式等效;
SELECT c.* ,s.* FROM student s LEFT OUTER JOIN classes c ON s.cid=c.cid;
SELECT c.* ,s.* FROM student s LEFT  JOIN classes c ON s.cid=c.cid;

//右外連接,在內鏈接基礎上,右邊有而左邊無,兩種方式等效;
SELECT c.* ,s.* FROM classes c RIGHT  OUTER JOIN student s ON s.cid=c.cid;
SELECT c.* ,s.* FROM classes c RIGHT  JOIN student s ON s.cid=c.cid;

HQL語句:
//查詢所有:
from Classes c,Student s where c.cid=s.classes.cid;
//選擇某些屬性查詢
select c.cname,s.sname from Classes c,Student s where c.cid=s.classes.cid;
//選擇某些屬性,封裝爲bean查詢;
select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  from Classes c,Student s where c.cid=s.classes.cid;
//內鏈接查詢,得到的是兩個bean
from Classes c inner join c.students s;
//內斂鏈接查詢,得到的是Classes對象,對象中包含studet集合
from Classes c inner join fetch c.students s;

from Student s inner join fetch s.classes c;

select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  from Student s inner join  s.classes c ;

from Classes c left outer join fetch c.students s;

from Student s left outer join fetch s.classes;


示例代碼:
如果加select,不能寫fetch,兩者只能選擇其一
/**
      * 1.一對多
      * sql:select c.*,s.* from classes c,student s where c.cid=s.cid;
      * hql:from Classes c,Student s where c.cid=s.classes.cid,注意與上句的區別;
      * 得到的list是object[],數組中的元素是Classes和Student對象;
      *
      */
     @Test
     public void testOneToMany_EQ(){
          Session   session = sessionFactory.openSession();
         Query query = session.createQuery( "from Classes c,Student s where c.cid=s.classes.cid");
         List list = query.list();
         System. out.println(query.list().size());
         session.close();
     }
     
     /**
      * 2.帶屬性的查詢;
      * list中裝的是object[];
      */
     @Test
     public void testOneToMany_EQ_Property(){
          Session   session = sessionFactory.openSession();
         Query query = session.createQuery( "select c.cname,s.sname from Classes c,Student s where c.cid=s.classes.cid");
         query.list();
         session.close();
     }
     /**
      * 3.帶屬性查詢,將查詢結果封裝成一個bean;
      * 得到的list中裝的是classView對象;
      */
     @Test
     public void testOneToMany_EQ_Property_Constructor(){
          Session   session = sessionFactory.openSession();
         Query query = session.createQuery( "select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname) " +
                "from Classes c,Student s where c.cid=s.classes.cid");
         List list = query.list();
        
         session.close();
     }
     
     /**
      * 4.內連接
      * 結果與例子1一樣;
      */
     @Test
     public void testOneToMany_InnerJoin_Query(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Classes c inner join c.students s");
         Query query = session.createQuery(buffer.toString());
         query.list();
         session.close();
     }
     
     /**
      * 5.迫切內連接1:獲取所有有學生的班級及班級下的學生;
      * 要想得到的集合中裝的Classes對象,對象中set集合中裝student,可以使用迫切內鏈接。
      *
      */
     @Test
     public void testOneToMany_InnerJoin_Fetch_Query_1(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Classes c inner join fetch c.students s");
         Query query = session.createQuery(buffer.toString());
         List list = query.list();
         session.close();
     }
     
     /**
      * 6.迫切內連接2
      * 從學生端出發;
      */
     @Test
     public void testOneToMany_InnerJoin_Fetch_Query_2(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Student s inner join fetch s.classes c");
         Query query = session.createQuery(buffer.toString());
         query.list();
         session.close();
     }
     
     /**
      * 7.迫切內連接3:獲取屬性,封裝結果;
      * select new cn.itheima03.hibernate.domain.ClassView(c.cname,s.sname)
      *   from Student s inner join fetch s.classes c;
      * 上述的 hql語句會報錯,因爲from後面想要的結構和select想要的結構是衝突的,所以
          如果在from後面加fetch,不能寫select語句,如果加select,不能寫fetch,兩者只能選擇其一
      *
      */
     @Test
     public void testOneToMany_InnerJoin_Fetch_Query_Property(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
           //下面的寫法不對;
//        buffer.append("select new cn.itheima03.hibernate.domain.ClassView(c.cname,s.sname) " +
//                 " from Student s inner join fetch s.classes c");
          
           //不要fetch;
          buffer.append( "select new cn.itheima03.hibernate.domain.ClassesView(c.cname,s.sname)  " +
           "  from Student s inner join  s.classes c " );
          
         Query query = session.createQuery(buffer.toString());
         List list = query.list();
         session.close();
     }
     
     /**
      * 8.迫切左外連接
      * 從班級出發,得到班級對應的學生
      */
     @Test
     public void testOneToMany_LeftJoin_Fetch(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Classes c left outer join fetch c.students s");
         Query query = session.createQuery(buffer.toString());
         List<Classes> list = query.list();
        
         for (Classes classes : list) {
               System. out.println("classes:" +classes.getCname());
              Set<Student> students = classes.getStudents();
               for (Student student : students) {
                   System. out.println("     student:" +student.getSname());
              }
          }
        
         session.close();
     }
     
     /**
      * 9.迫切左外連接2
      * 從學生出發,得到對應的班級
      */
     @Test
     public void testOneToMany_RightJoin_Fetch(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Student s left outer join fetch s.classes ");
         Query query = session.createQuery(buffer.toString());
         List<Student> list = query.list();
        
         for (Student student : list) {
               System. out.println("student:" +student.getSname());
               if (student.getClasses()!=null) {
                   System. out.println("     " +student.getClasses().getCname());
              }
          }
        
         session.close();
     }


二。多對多
學生Student和課程Course爲例:
Student裏有裝Course的set集合,Course裏也有裝Student的set集合;
多對多與一對多操作差不多
     /**
      * 1.得到所有的學生以及其對應的課程
      * 從學生端出發
      * list裝的是學生;
      */
     @Test
     public void testManyToMany_LeftJoin_Fecth(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Student s left outer join fetch s.courses");
         Query query = session.createQuery(buffer.toString());
         List list = query.list();
         session.close();
     }
     /**
      * 2.得到所有的課程及課程下對應的學生;
      * list裝的是課程
      */
     @Test
     public void testManyToMany_LeftJoin_Fecth_2(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Course c left outer join fetch c.students s");
         Query query = session.createQuery(buffer.toString());
         query.list();
         session.close();
     }
     
     /**
      * 3.一對多和多對多的結合
      * 得到所有班級下的所有學生以及所有學生下的所有課程;
      * 從班級出發
      */
     @Test
     public void testManyToManyAndOneToMany(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Classes c left outer join fetch" +
                    " c.students s left outer join fetch s.courses");
          
         Query query = session.createQuery(buffer.toString());
         List<Classes> classeList = query.list();
         //去掉集合中的重複元素
         Set<Classes> sets = new HashSet<Classes>(classeList);
         classeList = new ArrayList<Classes>(sets);
        
         System. out.println(classeList.size());
         for(Classes classes:classeList){//遍歷班級
          System. out.println(classes.getCname());
          Set<Student> students = classes.getStudents();//得到班級下的學生
           for(Student student:students){//遍歷學生
               System. out.println(student.getSname());
               Set<Course> courses = student.getCourses();
                for(Course course:courses){//遍歷學生下的課程
                   System. out.println(course.getCname());
               }
          }
         }
         session.close();
     }
     /**
      * 從中間表出發,班級有學生,學生修課程,故從學生角度出發進行查詢;
      */
     @Test
     public void testManyToManyAndOneToMany_2(){
          Session   session = sessionFactory.openSession();
          StringBuffer buffer = new StringBuffer();
          buffer.append( "from Student s left outer join fetch s.classes c 
                           left outer join fetch s.courses cc");
         Query query = session.createQuery(buffer.toString());
         List<Student> studentList = query.list();
         for(Student student:studentList){
          System. out.println(student.getSname());
          Classes classes = student.getClasses();
          System. out.println(classes.getCname());
          Set<Course> courses = student.getCourses();
           for(Course course:courses){
               System. out.println(course.getCname());
          }
         }
         session.close();
     }
     
     /*******************************************************************************/
        /**
         * 面向對象的查詢
         */
           @Test
           public void testQueryCriteria(){
              Session   session = sessionFactory.openSession();
              List<Classes>  classesList = session.createCriteria(Classes.class).list() ;
              System. out.println(classesList.size());
              session.close();
          }
          
           @Test
           public void testQueryCriteria_Where(){
              Session   session = sessionFactory.openSession();
              Classes classes = (Classes)session.createCriteria(Classes.class).add(Restrictions.eq("cid" , 1L)).uniqueResult();
              System. out.println(classes.getCname());
              session.close();
          }
}

總結:
無論是一對多還是多對多,hql語句中含有fetch時,得到的list裝的是From 後面的對象,對象中可能有相關聯對象的集合或者對象;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章