(17)抓取策略

 统计每一个专业的人数:

	void test17() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Object[]> objs=s.createQuery("select spe.name,count(stu.classroom.special.id) from Student stu right join stu.classroom.special spe group by spe.id").list();
   			for(Object[] obj:objs) {
   				System.out.println(obj[0]+":"+obj[1]);
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

 统计人数大于200的专业(用having):

	void test18() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Object[]> objs=s.createQuery("select spe.name,count(stu.classroom.special.id) from Student stu right join stu.classroom.special spe group by spe.id having count(stu.classroom.special.id)>200").list();
   			for(Object[] obj:objs) {
   				System.out.println(obj[0]+":"+obj[1]);
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

 统计每一个专业男生女生人数:

	void test19() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Object[]> objs=s.createQuery("select spe.name,stu.sex,count(stu.classroom.special.id) from Student stu right join stu.classroom.special spe group by spe.id,stu.sex").list();
   			for(Object[] obj:objs) {
   				System.out.println(obj[0]+":"+obj[1]+":"+obj[2]);
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

 基于XML:

	void test20() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			Student stu=s.load(Student.class, 1);
   			System.out.println(stu.getName()+","+stu.getClassroom().getName()+","+stu.getClassroom().getSpecial().getName());
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

执行该代码需要3条sql语句,因为延迟加载,如何解决?可以在Student.hbm.xml和Classroom.hbm.xml中的many-to-one中加入fetch="join",则完成join连接,一条sql语句搞定

缺点:当不需要classroom和special的数据时,也会自动完成连接,占用内存,降低效率,所以join看情况使用

 

基于annotation:annotation自动完成join操作,所以只需要一条语句,但是from student,没有获取classroom,也自动完成join操作,发2条语句

 	void test21() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Student> stus=s.createQuery("from Student").list();
   			for(Student stu:stus) {
   				System.out.println(stu.getName()+","+stu.getClassroom());
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

如何解决?获取student不需要获取classroom,把student的@ManyToOne修改为@ManyToOne(fetch=FetchType.LAZY),即延迟加载,不需要就不会获取了,所以就只发一条sql语句

 

	void test21() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Student> stus=s.createQuery("from Student").list();
   			for(Student stu:stus) {
   				System.out.println(stu.getName()+","+stu.getClassroom());
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

XML设置fetch=“join”对HQL语句不起作用,所以stu.getClassroom()并不会完成连接,而是先发查所有student的sql,查所有学生分别有哪些班级id,再发根据班级id查班级的sql

 

这个情况会发大量sql,如何解决?

(1).Classroom.java的@Entity下面加上@BatchSize(size=20),一次抓20个班级,不过这个方式不灵活

<hibernate-mapping>
    <class name="model.Classroom" table="CLASSROOM" batch-size="20">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="grade" type="int">
            <column name="GRADE" />
        </property>
        <set name="stus" inverse="true" lazy="extra" fetch="join">
            <key>
                <column name="c_id" />
            </key>
            <one-to-many class="model.Student" />
        </set>
        <many-to-one name="special" fetch="join" >
            <column name="spe_id" />
        </many-to-one>
    </class>
</hibernate-mapping>

注意: <class name="model.Classroom" table="CLASSROOM" batch-size="20">,batch-size="20"是在<class>里面的

 

 

(2).使用join fetch

void test22() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Student> stus=s.createQuery("select stu from Student stu join fetch stu.classroom cla").list();
   			for(Student stu:stus) {
   				System.out.println(stu.getName()+","+stu.getClassroom());
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

因为在XML中fetch=“join”语句对HQL不起作用,所以当使用join fetch可以把fetch=“join”删除,同时记得把BatchSize(size=20)删除,使用join fetch语句,只发一条sql就取到student和classroom的Name了

注意:使用joinFetch,就不能使用count
 

 

joinfetch(基于annotation):

annotation自动完成join,不过我们不需要取special,就把classroom中的manytoone加个lazy,不过对于HQL语句,from student还是先取student再取每一个班级,如何解决?用join fetch

 

在XML中针对1的抓取(单向关联):

	void test23() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			Classroom cla=s.load(Classroom.class, 1);
   			for(Student stu:cla.getStus()) {
   				System.out.println(stu.getName());
   			}
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

此时会发条sql,一条取此班级,一条根据此班级的id取该班级的学生,如果在set中加入fetch=“join”,则一条

 

在XML中子查询:

	void test26() {
   		Session s=null;
   		try {
   			s=HibernateUtil.getSession();
   		
   			List<Classroom> clas=s.createQuery("from Classroom").list();
   			
   			for(Classroom cla:clas) {
   				for(Student stu:cla.getStus()) {
   					System.out.println(stu.getName());
   				}
   			}
   			
   		} catch (Exception e) {
   			// TODO 自动生成的 catch 块
   			e.printStackTrace();
   			s.getTransaction().rollback();
   		}finally {
   			HibernateUtil.closeSession(s);
   		}
   	}

如果不使用子查询,会发大量sql,由于该代码是根据cla取stu,所以在cla的hbm中的set加入fetch="subselect",就实现子查询,条sql搞定

在annotation中子查询:

在getStus上面加入@Fetch(FetchMode.SUBSELECT)即可实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值