Проблема наследования Hibernate при использовании оператора hql - PullRequest
1 голос
/ 27 декабря 2010

Я столкнулся с проблемой в 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 список имеет два элемента в результате

  • 0 - счетчик из SuperField
  • 1 - счетчик изПоле

Естественно, это похоже на режим гибернации, выполнить оператор для иерархии классов, даже если сопоставления не связаны.

Кто-нибудь знает, что блокирует это поведение и загружает только объекты из одной таблицы?

PS.

То же самое относится и к критериям, но затем результат инвертируется

  • 0 - счетчик из поля
  • 1 - счетчик из SuperField

1 Ответ

1 голос
/ 27 декабря 2010

Интересное поведение.

Основная причина, по-видимому, такова ( 10.1.6. Таблица для каждого конкретного класса с использованием неявного полиморфизма ):

Недостатком этого подхода является то, что Hibernate не генерирует SQL UNION при выполнении полиморфных запросов.

Похоже, что вы можете решить эту проблему, перейдя к явной стратегии наследования таблицы-pre-concrete-class , хотя я не уверен, что делать с различными генераторами идентификаторов:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...