Исключение повторного столбца в спящем режиме - имя пользователя, объявленное дважды для связанных объектов «один ко многим» - PullRequest
0 голосов
/ 26 марта 2012

Получил классическую проблему гибернации:

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: entry.Authority column: username (should be mapped with insert="false" update="false")

users.hbm.xml:

<class name="entry.User" table="users">
    <property name="username" column="username"/>
    <set name="authorities" table="authorities" lazy="false" cascade="all">
        <key column="username" not-null="true"/>
        <one-to-many class="entry.Authority"/>
    </set>

authority.hbm.xml:

    <class name="entry.Authority" table="authorities">
        <id name="id"/>
        <property name="username" column="username"/>
    </class>

Испытанное классическое решение:

<property name="username" column="username"  insert="false" update="false"/>

Получено:

java.sql.BatchUpdateException: Field 'username' doesn't have a default value

Почему я не могу указать username дважды в.xml?
Насколько я понимаю, это объявление <property name="username" column="username"/> относится к User, а <key column="username" not-null="true"/> относится к Authorities
. Так почему они конфликтуют?
Как это можно исправить с минимальным вторжением?

РЕДАКТИРОВАНИЕ:

    <class name="entry.User" table="users">
        <id name="id">
            <generator class="increment" />
        </id>
        <property name="username" column="username"/>     
        <set name="authorities" table="authorities" lazy="false" cascade="all" inverse="true">
            <key column="username" not-null="true"/>
            <one-to-many class="entry.Authority"/>
        </set>
...

и

<class name="entry.Authority" table="authorities">
    <id name="id"/>
    <property name="username" column="username"/>
    <property name="authority" column="authority"/>
    <many-to-one name="user" class="entry.User">
             <column name="username"/>
     </many-to-one>
</class>

Ответы [ 3 ]

2 голосов
/ 29 марта 2012

С определением ключа в users.hbm.xml <key column="username" not-null="true"/> вы уже обрабатываете имя пользователя столбца в Authorities.Строка <property name="username" column="username"/> в authority.hbm.xml является излишней, даже если она используется во множестве к одному.Каждый раз, когда вы загружаете / обновляете или вставляете экземпляры Authorities через Users, поле автоматически обрабатывается Hibernate.Если вы определили это поле также в authority.hbm.xml, то оно устанавливается дважды - вот почему вы получили сообщение об ошибке.

Если вы по каким-то особым причинам действительно хотите, чтобы имя пользователя также было в авторизованном файле .hbm.xml, тогда вы должны указать insert / update = false (как вы уже сделали) и значение по умолчанию, чтобы избежать сообщения об ошибке (даже если значение по умолчанию никогда не используется).Например,

<property name="username" insert="false" update="false">
  <column="username" default="anyValue"/>
</property>

Но я бы просто порекомендовал это:

<class name="entry.Authority" table="authorities">
  <id name="id"/>
  <property name="authority" column="authority"/>
  <many-to-one name="user" class="entry.User">
         <column name="username"/>
   </many-to-one>
</class>

Добавлено после вашего комментария:

Теперь я вижу проблему в вашем новом отображении: элемент <key> должен ссылаться на ключ родительской таблицы, а это не так.Ключом в таблице Users является id, но вы используете обычное свойство Username в качестве внешнего ключа в Authority.Есть две возможности решить эту проблему:

1) Вы делаете Имя пользователя ключом Пользователя (удаляете идентификатор столбца и определяете ключ в Пользователях как

<id name="username">
 <column="username"/>
</id>

(я не уверен, еслив этом случае в новых экземплярах Authority hibernate установит имя пользователя участника автоматически или, если вам придется сделать это вручную.)

new: Вот полное сопоставление (не проверено):

<class name="entry.User" table="users">
  <id name="username" type="String">
    <column="username"/>
  </id>
  <property name="password" column="password" type="String"/>
  <property name="enabled" column="enabled" type="boolean"/>

  <set name="authorities" table="authorities" lazy="false" cascade="all" inverse="true">
    <key column="username" not-null="true"/>
    <one-to-many class="entry.Authority"/>
  </set>
</class>

2) Вы делаете id внешним ключом в Authority: в users.hbm.xml

<key column="id" not-null="true"/>

, а в author.hbm.xml имя пользователя столбца заменяется на

<property name="userId" column="userId"/>

Вы также должны изменить таблицу базы данных.

1 голос
/ 28 марта 2012

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

Редактировать: вы можете использовать propertyref, чтобы указать H присоединиться к другому свойству

<class name="entry.Authority" table="authorities">
    <id name="id"/>
    <many-to-one name="user" column="username" property-ref="username"/>
</class>

and 

<set name="authorities" inverse="true" property-ref="username">
0 голосов
/ 06 августа 2013

, если использование синтаксиса JPA будет таким (сделайте свою сторону не подлежащей обновлению): -

@JoinColumn(name = "", referencedColumnName = "", insertable = false, updatable = false)

Проблема в том, что двунаправленное отношение пытается обновить столбец еще раз

...