如果有一对多或者多对一的关联情况时:就要考虑抓取策略了。
如果不开启抓取策略,会分别发出sql语句来查询。如果有抓取策略,会在一次查询的时候把所有关联对象也会查询出来。
Student stu = (Student)session.load(Student.class, 1);
System.out.println(stu.getName()+","+stu.getClassroom().getName()+","+
stu.getClassroom().getSpecial().getName());
对于xml配置而言,默认情况就会发出三条sql语句,每一条sql取相应的对象,一条取Student,一条取Classroom,一条取Special。
可以通过设置添加:<many-to-onename="classroom"column="cid"fetch="join">
来设置join的抓取策略
Student此时还会发出两条sql语句,还需要设置Classroom中的<many-to-onename="special"column="spe_id"fetch="join">来设置join的抓取策略
此时就会发出一条sql语句了,会通过join自动抓取所有关联的数据。
但是抓取策略并不一定都是好的,使用fetch="join"虽然可以将关联对象一并抓取,但是即使不使用关联对象也会一并抓取出来,这样会占用相应的内存。延迟加载就失效了。
以下查询:
List<Student>stus = session.createQuery("from Student").list();
for(Student stu:stus) {
System.out.println(stu.getName()+","+stu.getClassroom());}
还是会发出很多sql语句。
原因是:
在XML中配置了fetch=join仅仅只是对load的对象有用,对HQL中查询的对象无用,真正涉及到creatQuery查询的时候,即使添加fetch="join"也无效。
所以此时会发出查询班级的SQL,解决的这个SQL的问题有两种方案,
1.一种是设置被关联对象的抓取的batch-size
Classroom2.另一种方案在HQL中使用fecth来指定抓取
List<Student>stus = session.createQuery("select stu from Student stu join fetch stu.classroom ").list();
for(Student stu:stus) {
System.out.println(stu.getName()+","+stu.getClassroom());}
此时会发出一条sql语句
特别注意,如果使用了join fetch就无法使用count(*)
对于Annotation的配置而言,默认就是基于join的抓取的,所以load的那个只会发出一条SQL。
但是当creatquery查询多条数据有关联对象的时候:
由于基于Annotation的配置没有延迟加载,此时会把所有的关联对象查询上来,发大量的SQL语句,所以要设置延迟加载:
由于启用了student的延迟加载,但是并没有启用classroom的延迟加载,所以上面的load语句会发出两条sql。
@ManyToOne(fetch = FetchType.EAGER)相当于xml中的
<many-to-onename="classroom"column="cid"fetch="join">
@ManyToOne(fetch = FetchType.LAZY)相当于xml中的
<many-to-onename="classroom"column="cid"fetch="select">
如果是后者的话,可以设置
1.
2 join feach
和xml基本类似。
以上是多的一方的查询
一的一方load的时候,可以设置set的feach="join"
一方creatQuery的时候
对于通过HQL取班级列表并且获取相应的学生列表时,fecth=join就无效了
* 第一种方案可以设置set的batch-size来完成批量的抓取
* 第二中方案可以设置fetch=subselect,使用subselect会完成根据查询出来的班级进行一次对学生对象的子查询
网友评论