Отображение двух таблиц 0..n в Hibernate - PullRequest
1 голос
/ 24 февраля 2010

У меня есть таблица Пользователи


CREATE TABLE "USERS" (
    "ID" NUMBER NOT NULL ,
    "LOGINNAME" VARCHAR2 (150) NOT NULL )

и у меня есть вторая таблица SpecialUsers. Никакой UserId не может встречаться дважды в таблице SpecialUsers, и только небольшая часть идентификаторов пользователей в таблице Users содержится в таблице SpecialUsers.


CREATE TABLE "SPECIALUSERS" (
    "USERID" NUMBER NOT NULL,
 CONSTRAINT "PK_SPECIALUSERS" PRIMARY KEY ("USERID") )

ALTER TABLE "SPECIALUSERS" ADD CONSTRAINT "FK_SPECIALUSERS_USERID" FOREIGN KEY ("USERID") 
REFERENCES "USERS" ("ID") 
/

Отображение таблицы Users в Hibernate работает нормально


<hibernate-mapping package="com.initech.domain">
    <class name="com.initech.User" table="USERS">

        <id name="id" column="ID" type="java.lang.Long">
            <meta attribute="use-in-tostring">true</meta>
            <generator class="sequence">
                <param name="sequence">SEQ_USERS_ID</param>
            </generator>
        </id>

        <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true">
            <meta attribute="use-in-tostring">true</meta>
        </property>

    </class>
</hibernate-mapping>

Но я изо всех сил пытаюсь создать сопоставление для таблицы SpecialUsers. Все примеры (например, в документации Hibernate) в Интернете, которые я обнаружил, не имеют такого рода ссылок на себя. Я попытался сопоставить как это:


<hibernate-mapping package="com.initech.domain">
    <class name="com.initech.User" table="SPECIALUSERS">        

        <id name="id" column="USERID">
            <meta attribute="use-in-tostring">true</meta>
            <generator class="foreign">
                <param name="property">user</param>
            </generator>
        </id>

        <one-to-one name="user" class="User"/>

    </class>
</hibernate-mapping>

но получил ошибку


Invocation of init method failed; nested exception is org.hibernate.DuplicateMappingException: 
Duplicate class/entity mapping com.initech.User 

Как мне сопоставить таблицу SpecialUsers? Что мне нужно на уровне приложения, так это список объектов User, содержащихся в таблице SpecialUsers.

Ответы [ 2 ]

2 голосов
/ 24 февраля 2010

Как мне сопоставить таблицу SpecialUsers?

Согласно структуре ваших USERS и SPECIALUSERS таблиц, у вас есть Таблица для каждого подкласса иерархия и , вполне возможно отобразить этот тип иерархии с Hibernate,

Сначала убедитесь, что SpecialUser наследует от User на уровне объектной модели (это отношение наследования, а не ссылка на себя).

public class SpecialUser extends User { 
}

Затем объявите элемент <joined-subclass> в отображении User:

<hibernate-mapping package="com.initech.domain">
    <class name="com.initech.User" table="USERS">

        <id name="id" column="ID" type="java.lang.Long">
            <meta attribute="use-in-tostring">true</meta>
            <generator class="sequence">
                <param name="sequence">SEQ_USERS_ID</param>
            </generator>
        </id>

        <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true">
            <meta attribute="use-in-tostring">true</meta>
        </property>

        <joined-subclass name="com.initech.SpecialUser" table="SPECIALUSERS">
            <key column="USERID"/>
        </joined-subclass>

    </class>
</hibernate-mapping>

На уровне приложения мне нужен список объектов User, содержащихся в таблице SpecialUsers.

Следующий HQL-запрос вернет все SpecialUser (которые тоже User):

from SpecialUser

Если позже вам потребуется добавить столбцы в таблицу SPECIALUSERS, добавьте соответствующие атрибуты в класс SpecialUser и отобразите их внутри элемента <joined-subclass>. Подробнее см. В предоставленной ссылке (к документации).

1 голос
/ 24 февраля 2010

Если вам действительно нужно использовать вторую таблицу, вы должны сопоставить ее с новым классом. Hibernate всегда может сопоставить только одну таблицу одному классу.

В качестве альтернативы, добавьте столбец в пользовательскую таблицу, который говорит, что «этот пользователь особенный». Если это не вариант, создайте представление, которое объединяет две таблицы и таким образом моделирует этот столбец. Затем вы можете выбрать пользователей по этому столбцу.

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

[РЕДАКТИРОВАТЬ] Может быть, вы должны посмотреть на отношения родителей и детей. В вашем случае пользователь является родителем, а его роли - детьми. Таким образом, у каждого пользователя есть 0..n ролей, которые отображаются в другой таблице. Затем вы можете использовать этот HQL

from User u where :role in elements(u.roles)

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

...