一、一對多
以班級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.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;
示例代碼:
/**
* 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 后面的對象,對象中可能有相關聯對象的集合或者對象;