【Hibernate的HQL多表联合查询使用left join方式】
Hibernate不支持left join带on的条件查询。
解决办法:使用原生SQL或者使用HQL方式需要修改hbm文件(如果项目中大部分不适用级联配置情况下)
需求是查询网络信息,网络信息中关联了分区、网络IP(1个网络--N个网络IP),网桥信息。
HQL:
public void queryVnets(Page page) {
StringBuffer hql = new StringBuffer();
hql.append("select new Map(vn.id as id, vn.vnName as vnName, b.name as vnType, ");
hql.append("vn.vnIptype as vnIptype, vn.vnIp as vnIp,vn.vnNat as vnNat, vn.vnFlag as vnFlag, ");
hql.append("vn.vnetFlag as vnetFlag, (case when sum(vmvn.state)='0' then 0 else 1 end) as vnState, ");
hql.append("vn.useType as useType, vn.createTime as createTime, ");
hql .append("zone.oneName as oneName, zone.oneHypervisor as oneHypervisor, zone.oneSeq as oneSeq) ");
hql.append("from VnetTable vn, ZoneTable zone, BridgeTable b ");
hql.append("left join fetch vn.VnTables vmvn where zone.id = vn.zoneId and vn.vnType = b.id ");
… …
hql.append(" group by vn.id");
if (vnState != null && !"".equals(vnState)) {
if ("0".equals(vnState)) {
hql.append(" having sum(vmvn.state)=0");
} else if ("1".equals(vnState)) {
hql.append(" having sum(vmvn.state)!=0");
}
}
}
hbm配置文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.base.mapping.VnetTable" table="vnet_table" >
<id name="id" type="java.lang.String">
<column name="ID" length="32" />
<generator class="uuid.hex" />
</id>
<property name="vnId" type="java.lang.Long">
<column name="VN_ID">
<comment>创建虚拟网络时得到的ID</comment>
</column>
</property>
…
<property name="zoneId" type="java.lang.String">
<column name="ZONE_ID" length="32">
<comment>分区ID</comment>
</column>
</property>
<property name="vlanId" type="java.lang.Integer">
<column name="VLAN_ID">
<comment>VLAN_ID</comment>
</column>
</property>
<set name="vnTables" lazy="false" order-by="id asc" inverse="false" fetch="join" cascade="all">
<key column="VN_NID"/>
<one-to-many class="com.base.mapping.VnTable"/>
</set>
</class>
</hibernate-mapping>
理解inverse和cascade,
总结:
<one-to-many>中,建议inverse="true",由"many"方来进行关联关系的维护
<many-to-many>中,只设置其中一方inverse="false",或双方都不设置
Cascade,通常情况下都不会使用。特别是删除,一定要慎重。
操作建议
一般对many-to-one和many-to-many不设置级联,这要看业务逻辑的需要;对one-to-one和one-to-many设置级联。
many-to-many关联关系中,一端设置inverse="false",另一端设置为inverse="true".在one-to-many关联关系中,设置inverse="true",由多端来维护关系表