2014-11-03 2 views
0

Я новичок в Hibernate, и я пытаюсь динамически присоединяться к другой таблице. Я построил пример с тремя таблицами: Employee, Address, Country. Я хочу получить всех сотрудников определенной страны. Вот мой конфигурационный файл:Спящий режим: динамическое объединение нескольких таблиц

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="address" column="address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

    <class entity-name="Address"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="street" column="street_name" type="string"/> 
     <property name="city" column="city_name" type="string"/> 
     <property name="state" column="state_name" type="string"/> 
     <property name="zipcode" column="zipcode" type="string"/> 

     <many-to-one name="country" column="country" unique="true" 
        class="Country" not-null="true"/> 
    </class> 

    <class entity-name="Country"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="name" column="name" type="string"/> 
     <property name="code" column="code" type="string"/> 
    </class> 

Если я

List employees = session.createCriteria("Employee") 
      .createCriteria("address") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

я получить правильный результат обратно, но моя цель состоит в том, чтобы не вручную указать полный путь между начальной таблицей и таблицами фильтров: Я хочу, чтобы спящий режим делает работу для меня. Я хотел бы написать что-то вроде этого:

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

, но я получаю сообщение об ошибке

org.hibernate.QueryException: could not resolve property: country of: Employee 

ответ

1

Hibernate это просто обертка или слой абстракции скрывались выражений SQL.

В вашем рабочем примере Hibernate создает инструкцию SQL select, создающую двойной JOIN и возвращающий желаемый результат. Вы загружаете Hibernate с «знаниями» о том, как фильтровать связанную таблицу. Точно так же, как вы должны написать свой собственный оператор SQL.

Но во втором примере вы ожидаете, что Hibernate угадает связь второго уровня с первой таблицей. Hibernate просто смотрит вверх, если стол Сотрудник имеет страну-столбец/внешний ключ, и он не находит его. Таким образом, ошибка: не удалось решить недвижимость: страна, в которой: Сотрудник

Вы не можете ожидать от Hibernate этого волшебства, поскольку оно создавало бы или вызывало бы ложные запросы.

Просто для иллюстрации на вашем примере.

В случае, если ваш сотрудник будет иметь два поля типа Адрес:

<class entity-name="Employee"> 
     <id name="id" type="int" column="id"> 
      <generator class="native"/> 
     </id> 
     <property name="firstName" column="first_name" type="string"/> 
     <property name="lastName" column="last_name" type="string"/> 
     <property name="salary" column="salary" type="int"/> 

     <many-to-one name="bussiness_address" column="bussiness_address" unique="true" 
        class="Address" not-null="true"/> 
     <many-to-one name="home_address" column="home_address" unique="true" 
        class="Address" not-null="true"/> 
    </class> 

Как бы страна, связана ... что должно в случае этого запроса Hibernate сделать?

List employees = session.createCriteria("Employee") 
      .createCriteria("country") 
      .add(Restrictions.eq("code","IT")) 
      .list(); 

Фильтр страны по дома или бизнес- адрес или оба? Или просто представьте случай, когда вы делаете фильтрацию на id Поле присутствует в каждом столе.

Итак, чтобы обернуть вещи: Hibernate не может делать магию, это только для того, чтобы скрыть необработанный SQL.

1

Если я переведу ваш запрос на язык Java, то вы пытаетесь получить значение coutry непосредственно из сотрудника. Однако в Java вы получите ошибку компиляции. Такая вещь автоматически не работает ни в Java, ни в Hibernate, ни в обычном SQL. Прямой связи между сотрудником и страной нет, но есть последовательность ссылок employee -> address -> country.

Чтобы исправить это на Java-пути, можно было бы переназначить вторичную ссылку на страну непосредственно у сотрудника. Затем вызов employee.getAddress(). GetCountry() и employee.getCountry() будут равны.

Чтобы достичь этого в спящем режиме, вам нужно будет добавить новую страну поля для Работника и отобразить ее как не изменяемое отношение «многие ко многим» с сущностью «Страна», используя объект «Адрес для сопоставления отношения». Это уменьшило бы только два спящего режима до одного, он не мог бы применяться повторно к более чем двум соединениям.

Если это решение подходит для вас, я могу предоставить вам пример синтаксиса.

+0

Хорошо, я понимаю ваше сравнение. Дело в том, что Hibernate имеет механизм запроса (builder), но он не способен динамически находить путь между двумя объектами на графике, как я предполагал. – Zardo

+0

Вы правы. Спящий режим требует соединения в запросе, чтобы указать путь от сотрудника к стране _ через_ объект адреса – OndrejM

Смежные вопросы