Композитный ключ с Hibernate - PullRequest
7 голосов
/ 15 апреля 2009

Для генерации следующего кода SQL:

create table users (
    user_name varchar(15) not null primary key, 
    user_pass varchar(15) not null);

create table user_roles(
    username varchar(15) not null,
    role_name varchar(15) not null, 
    primary key(usernmae, rolename)
);

Вы можете использовать код, такой как:

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="databaselayer.users.UserDB" table="users">
        <id name="username" type="string" column="user_name">
                <meta attribute="scope-set">public</meta>      
        </id>    
        <property name="password" type="string" column="user_pass"  not-null="true"/>
        <set name="roles" cascade="save-update" inverse="true">
                <key column="user_name"/>
                <one-to-many class="databaselayer.users.RoleDB"/>
        </set>                       
    </class>
   <class name="databaselayer.users.RoleDB" table="user_roles">
        <composite-id>
            <key-many-to-one name="username" class="databaselayer.users.UserDB" column="user_name"/>
            <key-property name="role" type="string" column="role_name"/>
        </composite-id>             
    </class>          
</hibernate-mapping>

Вам может потребоваться, чтобы ваши классы, а также файлы отображения hbm были указаны в вашем пути к классам.
Затем я опубликую свою цель схемы Ant:
Примечание $ {basedir} / build / WEB-INF / classes содержит файлы * .class и * .hbm.xml.

<target name="schema" description="Generate DB schema from the O/R mapping files">
    <hibernatetool destdir="${basedir}">            
        <classpath path="${basedir}/build/WEB-INF/classes">
            <fileset dir="${basedir}/build/WEB-INF/classes">
            <include name="**/*"/>
        </fileset>              
        </classpath>
        <configuration configurationfile="${basedir}/hibernate.cfg.xml"/>
        <hbm2ddl 
            drop="true" 
            create="true"
            export="true"
            outputfilename="libamo2-ddl.sql"
            delimiter=";"
            format="true"/>       
    </hibernatetool>
</target>

Ссылки по теме из документации по Hibernate

Составной идентификатор
Компоненты в качестве составного идентификатора

Ответы [ 4 ]

7 голосов
/ 15 апреля 2009

Посмотрите в документах hibernate для элемента 'Composite-ID'. Следующее может по крайней мере дать вам намерение - заменить ваш элемент id на:

<composite-id>
    <key-property name="username"/>
    <key-property name="role"/>
</composite-id>

Обратите внимание, что настоятельно рекомендуется вместо этого сделать ваш идентификатор отдельным классом ('компонентом'), который реализует hashCode и равен равно, и это Serializable. Иначе у вас будут только очень неуклюжие способы поиска вашего объекта, используя session.get() или session.load().

4 голосов
/ 21 августа 2014

Я добавляю к ответу Криса Уинтерса, но использую внешние ключи для его реализации. Вы можете написать:

<composite-id>
    <key-many-to-one name="username" class="com.foo.User" />
    <key-many-to-one name="role_id" class="com.foo.Role" />
</composite-id>

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

4 голосов
/ 15 апреля 2009

Может на самом деле что-то вроде этого:

<class name="User" table="users">
  <id name="username" column="user_name"/>
  <property name="password" column="user_pass" not-null="true"/>
  <set name="roles" table="user_roles">
    <key column="user_name"/>
    <element type="string" column="role_name" />
  </set>
</class>

Это сопоставит роли с коллекцией в классе User и будет примерно соответствовать схеме, которую вы дали. Хотя он не будет генерировать первичный ключ по столбцам в user_roles.

Как правило, вы получите лучшие результаты от Hibernate с более нормализованными схемами. Например, в этом случае у вас нет таблицы для самих ролей; но то, что вы, похоже, описываете, вполне естественно было бы смоделировать как класс User и Role с отношением «многие ко многим» между ними. Примерно так:

<class name="User" table="users">
  <id name="username" column="user_name"/>
  <property name="password" column="user_pass" not-null="true"/>
  <set name="roles" table="user_roles">
    <key column="user_name"/>
    <many-to-many column="role_name" class="Role"/>
  </set>
</class>
<class name="Role" table="roles">
  <id name="name" column="role_name"/>
</class>

Теперь это создаст схему с таблицами users, roles и user_roles, и теперь user_roles будет иметь первичный ключ в столбце имени пользователя и имени роли. Теперь вам также есть куда повесить дополнительную информацию о ролях, например описания.

Кроме того, ошибка, которую вы публикуете, - это ClassNotFoundException, что вряд ли является реальной проблемой с вашим отображением как таковым.

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

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

Серхио, посмотрите на это составное отображение ключей в спящем режиме Может помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...