I ran into a problem with Hibernate concerning hql query execution on classes which use inheritance.
Model Structure
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;
}
}
Mapping
<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>
Then we have two functions.
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);
}
The problem is that in function countFiledByName, list have two elements in result
- 0 - Count from SuperField
- 1 - Count 开发者_如何学Cfrom Field
Naturally this look like hibernate, execute the statement for class hierarchy even if the mappings are not related.
Does anyone know what lock this behavior and load only objects from one table ?
PS.
Same behavior goes for criteria, but then result is inverted
- 0 - Count from Field
- 1 - Count from SuperField
Interesting behaviour.
The root cause seems to be this (10.1.6. Table per concrete class using implicit polymorphism):
The disadvantage of this approach is that Hibernate does not generate SQL UNIONs when performing polymorphic queries.
Looks like you can solve this problem by swithing to explicit table-pre-concrete-class inheritance strategy, though I'm not sure what to do with different id generators:
<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>
精彩评论