抓取策略是指咱们须要在关联对象间进行导航的时候,Hibernate如何获取关联对象的策略。session
select抓取策略:当咱们查询某个对象时,hibernate会另外发出一条select语句查询与之关联的实体或者集合,也就是说当咱们在关联对象上设置了lazy=true,而且fetch=select的时候,咱们查询时,会首先查询该实体除关联对象外的其余属性。只有咱们使用到该实体的关联的对象时才会另外发出一条select语句查询关联对象。app
注意:这个方式为默认的抓取方式,在使用get/load方式或者使用hql语句查询时都是有效的。测试
例如:fetch
映射配置代码:ui
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="select" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> |
测试代码:spa
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); Transaction ts = session.beginTransaction(); String hql = "from Grade g where g.id=1"; Grade grade = (Grade) session.createQuery(hql).uniqueResult(); System.out.print("等级:"+grade.getGradeName()+" "+"成员:"); for(Student s:grade.getStuId()){ System.out.print(" "+s.getName()); } ts.commit(); session.close(); } |
join抓取策略:hibernate在select语句中经过left outer join 方法来获取关联实体或者实体集合的值,此时不管lazy的值是什么,hibernate都会在查询时当即把关联对对象的值查询出来。.net
注意:join抓取策略,只有在咱们使用get/load方式查询时有效,而使用hql语句查询时无效。hibernate
我的认为缘由:对象
使用hql语句的时候hibernate是直接读取hql语句进行查询,而hql语句中并无join链接关联对象,而使用get/load方式的时候是hibernate读取完配置文件以后拼写的hql语句,这里已经知道咱们配置了fetch,因此会加上join。ci
例如:
测试代码:
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); try{ Transaction ts = session.beginTransaction(); Grade grade = (Grade) session.load(Grade.class, 1); System.out.print("等级:"+grade.getGradeName()+" "+"成员:"); for(Student s:grade.getStuId()){ System.out.println(" "+s.getName()); } ts.commit(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { session.close(); } } |
映射配置代码:
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="join" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> |
subselect抓取策略:当咱们查询某个对象时,hibernate会另外发出一条select语句查询与前面查询关联的全部的集合,与select抓取策略不一样的是当咱们用到一个关联对象的时候,hibernate会把前面查询出来的实体相关联的集合所有查询出来,而select策略查询的时候是用到前面查询的哪一个对象的关联对象,就查询哪一个对象的关联实体。
注意:subselect抓取策略在使用get/load方式或者使用hql语句查询时都是有效的。这时候lazy只是影响咱们查询关联对象集合的时机。只有在一对多的一端或者多对多的状况下,才有subselect抓取策略。在一对多的多端没有subselect抓取策略。
例如:
映射配置代码:
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="subselect" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> |
测试代码:
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); try{ Transaction ts = session.beginTransaction(); List<Grade> results = session.createCriteria(Grade.class).add(Restrictions.in("id", new Integer[]{1,2})).list(); for(Grade g:results){ System.out.print("等级:"+g.getGradeName()+" "+"成员:"); for(Student s:g.getStuId()){ System.out.print(" "+s.getName()); } System.out.println(); } ts.commit(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { session.close(); } } |
解释:这个测试代码当程序走到for(Student s:g.getStuId())里的时候hibernate会查询id=1和id=2的关联对象的信息。而若是是select抓取策略则是循环第二轮的时候才会查询id=2关联的对象信息,也就是id=1和id=2关联对象的信息是经过两条select语句查询的。