hibernate的一对多时即时抓取策略
组织机构是一颗树型机构,一个父类对应多个子类。该对象的xml文件为
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class table="g_organization" name="com.going.platform.model.Organization"> <cache usage="read-write" region="com.going.platform.model.Organization"/> <id access="field" name="id" type="java.lang.String" column="ID" length="32"> <generator type="string" length="50" not-null="true"> <column name="ORGANIZATION_NAME"> <comment>机构名称</comment> </column> </property> <property name="description" type="string" length="200"> <column name="DESCRIPTION"> <comment>职能描述</comment> </column> </property> <many-to-one column="PID" access="field" name="parent" not-found="ignore"/> <set inverse="true" access="field" name="childern" cascade="save-update,persist" order-by="ORDER_NUM"> <key column="PID"/> <one-to-many type="string" length="20"> <column name="ORGANIZATION_TEL"> <comment>部门电话</comment> </column> </property> <property name="orderNum" type="java.lang.Integer"> <column name="ORDER_NUM" length="5"> <comment>排序号</comment> </column> </property> </class></hibernate-mapping>
形成机构树时,需要查询出所有节点,并且会根据节点来获取子节点。所以应该采用即时抓取。
方法一:设置lazy为false 也就是即时抓取
使用getHibernateTemplate().loadAll(Organization.class);能达到目的但会发出n+1条sql语句
select this_.ID as ID0_0_, this_.ORGANIZATION_NAME as ORGANIZA2_0_0_, this_.DESCRIPTION as DESCRIPT3_0_0_, this_.PID as PID0_0_, this_.ORGANIZATION_TEL as ORGANIZA5_0_0_, this_.ORDER_NUM as ORDER6_0_0_ from g_organization this_Hibernate: select childern0_.PID as PID1_, childern0_.ID as ID1_, childern0_.ID as ID0_0_, childern0_.ORGANIZATION_NAME as ORGANIZA2_0_0_, childern0_.DESCRIPTION as DESCRIPT3_0_0_, childern0_.PID as PID0_0_, childern0_.ORGANIZATION_TEL as ORGANIZA5_0_0_, childern0_.ORDER_NUM as ORDER6_0_0_ from g_organization childern0_ where childern0_.PID=? order by childern0_.ORDER_NUM。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
第一条sql查询出所有记录,接下来会发出n条记录来获取所有相关的子记录。查询时间大概
20:26:18,105 INFO OrganizationBoTest:51 - *******发费时间******203
所以可以看出这种方式并不是最佳选择。
方法二: 设置抓取策略fetch="join" 并loadAll时只发送一条sql语句 fetch="join"只对load和get方法 还有就是条件查询会起作用,而对hsql的查询是不会有影响的
select this_.ID as ID0_1_, this_.ORGANIZATION_NAME as ORGANIZA2_0_1_, this_.DESCRIPTION as DESCRIPT3_0_1_, this_.PID as PID0_1_, this_.ORGANIZATION_TEL as ORGANIZA5_0_1_, this_.ORDER_NUM as ORDER6_0_1_, childern2_.PID as PID3_, childern2_.ID as ID3_, childern2_.ID as ID0_0_, childern2_.ORGANIZATION_NAME as ORGANIZA2_0_0_, childern2_.DESCRIPTION as DESCRIPT3_0_0_, childern2_.PID as PID0_0_, childern2_.ORGANIZATION_TEL as ORGANIZA5_0_0_, childern2_.ORDER_NUM as ORDER6_0_0_ from g_organization this_ left outer join g_organization childern2_ on this_.ID=childern2_.PID order by childern2_.ORDER_NUM
发费时间大概为
20:28:01,450 INFO OrganizationBoTest:51 - ********发费时间*****178
但存在一个问题就是,对于许多其他查询应用可能不会操作子记录,也就没有立即抓取子节点的必要,而且这样会浪费内存。