Hibernate Сохранить странное поведение - PullRequest
5 голосов
/ 09 июля 2009

У меня есть пользовательский объект, который имеет отношение один ко многим с типами String. Я считаю, что они простые отображения. В таблице типов хранятся связанные имена пользователей и идентификаторов типов переменных с первичным ключом id, который в основном является счетчиком.

<class name="Users" table="users">
    <id column="id" name="id" />
    ...
    <set name="types" table="types" cascade="save-update">
        <key column="id" />
        <one-to-many class="Types" />
    </set>
</class>

<class name="Types" table="types">
    <id column="id" name="id" />
    <property column="user_id" name="user_id" type="integer" />
    <property column="type" name="type" type="string" />
</class>

Это Java, который я использовал для добавления в базу данных:

User u = new User();
u.setId(user_id);
...
Collection<Types> t = new HashSet<Types>();
t.add(new Type(auto_incremented_id, user_id, type_name));
u.setTypes(t);

getHibernateTemplate().saveOrUpdate(u);

Когда я запускаю его, он выдает эту ошибку:

61468 [http-8080-3] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000
61468 [http-8080-3] ERROR org.hibernate.util.JDBCExceptionReporter - Duplicate entry '6' for key 'PRIMARY'
61468 [http-8080-3] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

Когда я проверяю sql, он показывает:

Hibernate: insert into users (name, id) values (?, ?)
Hibernate: insert into types (user_id, type, id) values (?, ?, ?)
Hibernate: update types set id=? where id=?
  • Почему Hibernate пытается обновить id типов?

Ошибка говорит: Дублирующая запись '6' для ключа 'ПЕРВИЧНАЯ', но на самом деле это не так? Я убедился, что идентификаторы увеличиваются каждый раз. И пользователи и типы добавляются в базу данных правильно.

Я зарегистрировал входящую информацию, и добавленные типы имеют идентификатор 7 и идентификатор пользователя 6. Может ли быть, что Hibernate берет user_id 6 и пытается обновить типы и установить id = 6, где id = 7 ? Следовательно, ошибка дублирования первичного ключа?

Но с чего бы это так странно? Есть ли способ остановить его обновление?

  • Должен ли я установить идентификатор вручную? Если нет, то как мне добавить типы? Это дает другие ошибки, когда я добавляю объект типа, в котором есть только строка типа и нет идентификаторов.

Спасибо, ребята. Обдумывал это в течение нескольких дней ...

Ответы [ 2 ]

2 голосов
/ 10 июля 2009

Ваша самая большая проблема - неправильный столбец в отображении <key> - это должен быть "user_id", а не "id". Тем не менее, все ваше отображение кажется мне немного странным.

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

 <id column="id" name="id">
   <generator class="native"/>
 </id>

Чтение Документация Hibernate на генераторах для различных доступных опций.

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

 <set name="types" table="types">
    <key column="user_id"/>
    <element column="type" type="string"/>
 </set> 

Таким образом, вам не понадобится явный класс "Types" или его отображение. Даже если вы хотите иметь дополнительные атрибуты для «Типов», вы все равно можете отобразить их как компонент, а не как сущность.

Наконец, если «Типы» должны быть сущностью из-за какого-то требования, которое вы не описали, связь между «Пользователи» и «Типы» является двунаправленной и должна отображаться следующим образом:

 <set name="types" table="types" inverse="true">
    <key column="user_id"/>
    <one-to-many class="Types"/>
 </set>

 ...
 in Types mapping:
 <many-to-one name="user" column="user_id" not-null="true"/>

В последнем случае «Типы» должны иметь свойство «пользователь» типа «Пользователи». Здесь - подробный пример.

0 голосов
/ 10 июля 2009

Решение, которое работало для меня, состояло в том, чтобы отдельно сохранить две части (без добавления типа для пользователя):

getHibernateTemplate().save(user);
getHibernateTemplate().save(new Type(user.id, type_name));

И с только для идентификаторов типов.

Плохая практика?

Сопоставил его как набор элементов, но несколько ошибочно добавлял user_id в столбец ID типов, что иногда вызывает ошибку дублирования; поскольку тип ID является единственным столбцом первичного ключа. Weird! Я вроде помню, что была какая-то другая ошибка в столбце, но забыл об этом, потому что я сразу же вернулся к одному ко многим. Не мог понять странную работу Hibernate ...

Я когда-нибудь попробую двунаправленное решение ... Большое спасибо за помощь:)

...