【问题标题】:Hibernate Save strange behaviour休眠保存奇怪的行为
【发布时间】:2009-07-09 18:33:17
【问题描述】:

我有一个与字符串类型具有一对多关系的用户对象。我相信它们是简单的映射。 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 采用了 6 的 user_id 并尝试更新类型并设置 id=6 where id=7 ?所以主键重复错误?

但它为什么会做出如此奇怪的事情呢?有没有办法阻止它更新?

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

谢谢各位。这几天一直在琢磨……

【问题讨论】:

    标签: java mysql hibernate mysql-error-1062


    【解决方案1】:

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

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

    阅读Hibernate Documentation 上有关生成器的各种可用选项。

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

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

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

    ... 在类型映射中:

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

    【讨论】:

    • 卡在元素集合上!谢谢!
    【解决方案2】:

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

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

    并且仅在类型 id 上使用 。

    不好的做法?

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

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

    【讨论】:

    • 恐怕你完全没有抓住重点。您应该让 Hibernate 让您的生活更轻松,而不是每一步都与之抗争——拥有正确的映射将大大有助于实现这一目标。您上面描述的场景非常基本;有很多可用的示例(我在答案中发布了链接)。您确实需要通读文档,使其正常工作并了解 如何 它是如何工作的;否则会变得更加困难。
    • 是的,我知道它非常基本,所以我很困惑为什么它仍然会损坏。使用此解决方案,hibernate 尝试通过将类型 id 与 user_id 匹配来搜索类型,这完全是奇怪的。所以我做了上面提到的元素集合,现在有类转换错误。为 Hibernate 制作映射让生活变得如此困难!每次有映射时,他们都不会跟进如何访问或检索对象的方式。你必须在其他地方搜索和挖掘。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 2018-12-11
    相关资源
    最近更新 更多