我遇到了Hibernate的问题,涉及使用继承的类的hql查询执行。
模型结构
public class Filed {
private Long id;
private String name;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName(){
this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class SuperField extend Field {
private String role;
public String getRole(){
return this.role;
}
public void setRole(String role) {
this.role = role;
}
}
映射
<hibernate-mapping>
<class name="org.stackoveflow.Field" table="FILEDS" schema="STACK">
<id name="id" type="java.lang.Long">
<column name="FILED_ID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">STACK.FIELDS_SEQ</param>
</generator>
</id>
<property name="name" type="string" column="NAME"/>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="org.stackoveflow.SuperField" table="SUPER_FILEDS" schema="STACK">
<id name="id" type="java.lang.Long">
<column name="FILED_ID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">STACK.SUPER_FIELDS_SEQ</param>
</generator>
</id>
<property name="name" type="string" column="NAME"/>
<property name="role" type="string" column="ROLE"/>
</class>
</hibernate-mapping>
然后我们有两个功能。
public Long countFiledByName(String name) {
String query = "select count(*) from Filed Field where Field.name = :fieldName";
List<?> list = getHibernateTemplate().findByNamedParam(query, new String[] {fieldName},new Object[] { name});
return (Long) list.get(0);
}
public Long countSuperFieldByName(String name) {
String query = "select count(*) from SuperFiled SuperField where SuperField.name = :superFieldName";
List<?> list = getHibernateTemplate().findByNamedParam(query, new String[] {"superFieldName"},new Object[] { name});
return (Long) list.get(0);
}
问题是在函数countFiledByName中,list在result
中有两个元素当然,这看起来像hibernate,即使映射不相关,也要执行类层次结构的语句。
有谁知道锁定此行为是什么,只加载一个表中的对象?
PS。
标准的行为相同,但结果反转
答案 0 :(得分:1)
有趣的行为。
根本原因似乎是这个(10.1.6. Table per concrete class using implicit polymorphism):
这种方法的缺点是Hibernate在执行多态查询时不会生成SQL UNION。
看起来你可以通过切换到显式table-pre-concrete-class inheritance strategy来解决这个问题,虽然我不知道如何处理不同的id生成器:
<hibernate-mapping>
<class name="org.stackoveflow.Field" table="FILEDS" schema="STACK">
<id name="id" type="java.lang.Long">
<column name="FILED_ID" precision="22" scale="0" />
<generator class="sequence">
<param name="sequence">STACK.FIELDS_SEQ</param>
</generator>
</id>
<property name="name" type="string" column="NAME" />
<union-subclass name = "org.stackoveflow.SuperField" table = "SUPER_FILEDS" schema = "STACK">
<property name="role" type="string" column="ROLE"/>
</union-subclass>
</class>
</hibernate-mapping>