SSHM四大框架

Hibernate之抓取策略

2016-08-20  本文已影响27人  昵称已被占用了啊

如果有一对多或者多对一的关联情况时:就要考虑抓取策略了。

如果不开启抓取策略,会分别发出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

Classroom

2.另一种方案在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会完成根据查询出来的班级进行一次对学生对象的子查询

上一篇下一篇

猜你喜欢

热点阅读