Каскадная проблема Java Hibernate

---- Информационная и проблемная область ----

В основном у меня есть 3 таблицы в базе данных: "Пользователь", "Элемент", "ItemsPerUser".

Пользователь таблицы:

имя пользователя (PK); пароль; электронная почта

Элемент таблицы

name (PK)

Элементы таблицыPerUser

имя пользователя (PK) (и FK); item_name (PK) (и FK)

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

Файлы сопоставления верны. Мне нужен какой-то каскадный. Он работает, когда я добавляю каскадирование в свойство set отношения "многие ко многим" для добавления несуществующих данных в Пользователь и элемент, но это переписывание данных в ItemsPerUser. Всякий раз, когда я сохраняю объект, содержащий один или несколько элементов, которые уже были введены в ItemsPerUser, он перезаписывает строку, даже если другая часть PK не является тем же самым пользователем. Таким образом, предыдущий пользователь с этим "элементом" перезаписывается новым пользователем с тем же элементом. Он всегда должен добавлять новую строку в таблицу ItemsPerUser, если она является новым пользователем, даже с одним или несколькими элементами, которые уже введены другим объектом пользователя.

---- Пример в стиле с изображением ----

Предположим, что я начинаю с пустой базы данных, и я ввожу нового пользователя Roger, у которого есть два предмета: кофе и вода. Это пример того, что происходит (Hibernate обрабатывает это правильно):

User ItemsPerUser Item 
Roger Roger-coffee coffee 
 Roger-water water

Теперь, когда я ввожу нового пользователя "Альфонсо", у которого есть предметы кофе и соды, это происходит:

User ItemsPerUser Item 
Roger Alfonzo-coffee coffee 
Alfonzo Roger-water water 
 Alfonzo-soda soda

---- Пример кода ----

//Mapping for databag 'User' - !! NOTE: I have deleted the cascade rule in the XML
<hibernate-mapping>
 <class name="databag.User" table="User" catalog="androiddb">
 <id name="username" type="string">
 <column name="username" length="45">
 <generator>
 </generator></column></id>
 <property name="password" type="string">
 <column name="password" length="45" not-null="true">
 </column></property>
 <property name="email" type="string">
 <column name="email" length="45" not-null="true" unique="true">
 </column></property>
 <set name="items" inverse="false" table="itemsperuser">
 <key>
 <column name="username" length="45" not-null="true">
 </column></key>
 <many-to-many entity-name="databag.Items">
 <column name="item_name" length="45" not-null="true">
 </column></many-to-many>
 </set>
 </class>
</hibernate-mapping>
//Mapping for Item
<hibernate-mapping>
 <class name="databag.Item" table="item" catalog="androiddb">
 <id name="name" type="string">
 <column name="name" length="45">
 <generator>
 </generator></column></id>
 <set name="users" inverse="false" table="itemsperuser">
 <key>
 <column name="item_naam" length="45" not-null="true">
 </column></key>
 <many-to-many entity-name="databag.User">
 <column name="username" length="45" not-null="true">
 </column></many-to-many>
 </set>
 </class>
</hibernate-mapping>
//Saving an object
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction trans = session.beginTransaction();
session.save((User)o);
trans.commit();
session.close();

Примечание: '(Пользователь) o' не содержит ни одного, одного или нескольких элементов.

1 ответ

Вы не можете установить inverse = "false" с обеих сторон. Hibernate не может сохранять оба набора (пользователи в элементе и элементы в пользователе) в той же таблице, если только один из них не называется "обратным" и может быть легко проигнорирован для записи. Он будет заполнен только при чтении.

Я бы установил inverse = "true" на стороне Item.

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

licensed under cc by-sa 3.0 with attribution.