一对多的查询又包含以下情况:
1、等值连接
2、内连接
3、迫切内连接
4、左外连接
5、迫切左外连接
1、等值连接:一对多查询的时候,由于使用的hql语句,是根据类来查询的,所以hql语句这样表示:
/**
* 等值连接
*/
public void Connect_equal(){
Session session=sessionFactory.openSession();
//因为hql语句,是根据pojo类来查询的,所以这里要用到类名
//又因为Student没有cid属性,但是有classes属性,所以通过classes获得cid
String hql="from Classes c,Student s where c.cid=s.classes.cid";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
运行之后的List集合的结构:
在单表查询中,我们说过。结构为数组的形式不好遍历
那我们就来试一下内连接:
/**
* 内连接
*/
public void Connect_inner(){
Session session=sessionFactory.openSession();
String hql="from Classes c inner join Student s on(c.cid=s.classes.cid)";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
我们根据sql的基础,理所当然的使用了上面的查询语句,可是运行之后报错了,
可是执行如下语句的时候,通过了
public void Connect_ineer2(){
Session session=sessionFactory.openSession();
//在使用hql语句的时候,要处处想着我们使用的是类,而不是表!!
String hql="from Classes c inner join c.students";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
运行之后,集合的结构为:
虽然说等值连接跟内连接的效果是一样的,但是它们的产生的集合结构也是一样的。
由于这种结构的不完善,所以就出现了迫切内连接:
public void fetch_inner(){
Session session=sessionFactory.openSession();
String hql="from Classes c inner join fetch c.students";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
迫切内连接,只需要在内连接的join后面 加上fetch 即可
运行之后的 结果为:
这时,list集合里面的内容为对象,而不是数组
有时候根据需求,我们要查询所有的数据,所以我们要用到左连接
/**
左外连接
*/
public void Connect_leftJoin(){
Session session=sessionFactory.openSession();
String hql="from Classes c left join c.students";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
运行之后的集合结构为:
,经过上面几种连接, 我们可以发现,都是迫切连接,才能解决结构为数组的问题,所以我们用迫切左外连接来做一下
/**
* 迫切左外连接
*/
public void Connect_fetch_join(){
Session session=sessionFactory.openSession();
String hql="from Classes c left join fetch c.students";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
运行之后,list的结构为:
另外,如果我们需要的数据,与表中的字段数相差太多,我们可以自己建立一个javaBean,然后把我们自己需要的数据定义在javaBean里面,并且把带参和空参的构造函数创建好。然后我们就可以使用new的方法来进行连接查询:
/**
* 带select的左外连接查询
*/
public void Select_join2(){
Session session=sessionFactory.openSession();
String hql="select new cn.ansel.domain.ClassView(c.cname,s.sname) from Student s left join s.classes c";
List<Classes> classes=session.createQuery(hql).list();
session.close();
}
运行之后:
细心的可以发现,上面带select的语句,我既没有用
select new cn.ansel.domain.ClassView(c.cname,c.students.sname) from Classes c left join fetch c.students
又没有用这样
select new cn.ansel.domain.ClassView(c.cname,c.students.sname) from Classes c left join c.students
的语句进行查询,因为第一句,new构造函数的方法,不适合于fecth一起使用,二者选一,又因为第二种的c.students.sname属性为多的一方,在这里只是获取属性,而不是遍历,不知道指向哪个对象。所以我们要用Student放在前面,因为student与classes是多对一的关系,所以我们当前的student都能获到唯一的classes,所以使用student在前面。
下面我们来说说new构造函数这种方法的弊端:
由于一般的项目,我们都是通过用户在页面输入数据,然后把数据传送到action中,这时候接受数据的比如是Classes类,然后由于我们只需要用户输入数据的一两种(比用户输入的字段数量少得多的情况下),所以我们要另外创建一个javaBean,把我们需要在页面上显示的数据定义为该javaBean的属性,然后设置好getter&setter以及带参&空参构造函数之后,我们调用service和dao来保存这个用户,由于我们自己创建的javaBean与用户输入的Classes不一样,所以我们要在Dao操作之前,要对javaBean进行处理。这个处理可能简单,也可能很麻烦