Hibernate在使用hql语句时继承问题

时间:2010-12-27 15:53:51

标签: hibernate inheritance hql

我遇到了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

中有两个元素
  • 0 - 来自SuperField的数量
  • 1 - 来自Field的数量

当然,这看起来像hibernate,即使映射不相关,也要执行类层次结构的语句。

有谁知道锁定此行为是什么,只加载一个表中的对象?

PS。

标准的行为相同,但结果反转

  • 0 - 来自Field的计数
  • 1 - 来自SuperField的数量

1 个答案:

答案 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>