Hibernate保存奇怪的行为

时间:2009-07-09 18:33:17

标签: java mysql hibernate mysql-error-1062

我有一个与String类型具有一对多关系的用户对象。我相信它们是简单的映射。 types表包含关联的user_id和变量类型名称,主键'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?

错误说:关键'PRIMARY'重复输入'6',但确实没有?我确保每次都会增加ID。并且用户和类型正确地添加到数据库中。

我记录了进入的信息,添加的类型的id为7,用户ID为6.可能是Hibernate的user_id为6并尝试更新类型并设置id = 6,其中id = 7 ?因此重复的主键错误?

但为什么会这么奇怪呢?有没有办法阻止它更新?

  • 我应该手动设置ID吗?如果没有,那么我应该如何添加类型?当我添加一个只有一个类型字符串且没有ids的类型对象时,它会产生其他错误。

谢谢你们。几天来一直在考虑它......

2 个答案:

答案 0 :(得分:2)

您最大的问题是<key>映射中的列不正确 - 它应该是“user_id”,而不是“id”。也就是说,你的整个映射对我来说有点奇怪。

首先,如果你想自动生成ID,你应该让Hibernate通过指定合适的生成器来处理它:

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

在生成器上阅读Hibernate Documentation以获取各种可用选项。

其次,如果您只需要一组字符串类型,请考虑将它们重新映射到元素集合而不是一对多关系:

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

这样您就不需要显式的“类型”类或映射。即使您确实希望在“类型”上有其他属性,您仍然可以将其映射为组件而不是实体。

最后,如果“类型”由于您未描述的某些要求而必须是实体,则“用户”和“类型”之间的关系是双向的,需要按原样映射:

 <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"/>

在后一种情况下,“类型”必须具有“用户”类型的“用户”属性。 Here是一个详细的例子。

答案 1 :(得分:0)

对我有用的解决方案是分别保存这两部分(不向用户添加类型):

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

并且&lt; generator class =“native”/&gt;仅在类型id。

不良做法?

已将其映射为元素集合,但将user_id添加到types id列有时会错误地导致重复错误;因为types id是唯一的主键列。奇怪的!我记得有一些其他的列错误,但忘了它,因为我立即恢复到一对多。无法掌握Hibernate的奇怪工作......

我会尝试双向解决方案...非常感谢所有帮助:)