Hibernate 保存奇怪的行为

发布于 2024-07-27 16:32:10 字数 1992 浏览 8 评论 0原文

我有一个与 String 类型具有一对多关系的用户对象。 我相信它们是简单的映射。 类型表保存关联的 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=?
  • Why does Hibernate try to update the types' id?

错误提示:“PRIMARY”键的条目“6”重复,但实际上没有? 我确保 id 每次都会递增。 并且用户和类型已正确添加到数据库中。

我记录了输入的信息,添加的类型的 id 为 7,用户 id 为 6。难道 Hibernate 采用 user_id 6 并尝试更新类型并设置 id=6 其中 id=7? 因此重复主键错误?

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

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

多谢你们。 想了好几天了...

I have a user object that has a one-to-many relationship with String types. I believe they are simple mappings. The types table hold the associated user_id and variable type names, with a primary key 'id' that is basically a counter.

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

This is the java I used for adding to the database:

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);

When I run it, it gives this error:

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

When I check the sql, it shows:

Hibernate: insert into users (name, id) values (?, ?)
Hibernate: insert into types (user_id, type, id) values (?, ?, ?)
Hibernate: update types set id=? where id=?
  • Why does Hibernate try to update the types' id?

The error says: Duplicate entry '6' for key 'PRIMARY', but there really isn't? I made sure the ids are incremented each time. And the users and types are added into the database correctly.

I logged the information going in, and the types added has an id of 7 and a user id of 6. Could it be that Hibernate takes the user_id of 6 and tried to update types and set id=6 where id=7? Therefore the duplicate primary key error?

But why would it do something so strange? Is there a way to stop it from updating?

  • Should I set the id manually? If not, then how should I add the types? It gives other errors when I add a type object that only has a type string in it and no ids.

Thanks guys. Been mulling over it for days...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

執念 2024-08-03 16:32:11

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

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

对我有用的 生成器类=“本机”/> 仅在类型 id 上。

不好的做法?

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

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

The solution that worked for me was to separately save the two parts (without adding type to user):

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

And with the < generator class="native" /> on only the types id.

Bad practice?

Had mapped it as a collection of elements, but it was somewhat wrongly adding the user_id to the types id column which causes duplicate error sometimes; since types id is the only primary key column. Weird! I sort of remember there was some other column error, but forgot about it, because I immediately reverted back to one-to-many. Couldn't grasp the strange workings of Hibernate...

I will try the bi-directional solution sometime... Thanks a lot for all the help :)

沦落红尘 2024-08-03 16:32:10

您最大的问题是 映射中的列不正确 - 它应该是“user_id”,而不是“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"/>

在后一种情况下,“类型”将具有具有“用户”类型的“用户”属性。
这里是一个详细的示例。

Your biggest problem is incorrect column in the <key> mapping - it should be "user_id", not "id". That said, your whole mapping seems a bit strange to me.

First of all, if you want IDs auto generated you should really let Hibernate take care of that by specifying appropriate generator:

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

Read Hibernate Documentation on generators for various available options.

Secondly, if all you need is a set of string types, consider re-mapping them into a collection of elements rather than one-to-many relationship:

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

That way you won't need explicit "Types" class or mapping for it. Even if you do want to have additional attributes on "Types", you can still map it as component rather than entity.

Finally, if "Types" must be an entity due to some requirement you have not described, the relationship between "Users" and "Types" is bi-directional and needs to be mapped as such:

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

In the latter case "Types" would have to have a "user" property of type "Users".
Here is a detailed example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文