Java 在 Hibernate 中使用 saveOrUpdate() 创建新记录而不是更新现有记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2857490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using saveOrUpdate() in Hibernate creates new records instead of updating existing ones
提问by kunkanwan
I have a class User
我有一个类用户
class User {
int id;
String name;
}
where id
is native generator in User.hbm.xml
and name
is primary-key in DB.
其中id
是本地生成器User.hbm.xml
,name
是数据库中的主键。
In my database I saved some information about Users.
在我的数据库中,我保存了一些关于用户的信息。
Than I want to connect with this information about User.
比我想与有关用户的这些信息联系起来。
For example in my DB I have a row INSERT INTO User VALUES ('Bill');
例如在我的数据库中,我有一排 INSERT INTO User VALUES ('Bill');
Main.java
主程序
User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);
This code always tries to insert a new Bill
row into the table rather than update the existing Bill
row.
此代码始终尝试向表中插入新Bill
行,而不是更新现有Bill
行。
回答by Frederik Gheysels
So, Id is not saved in the database ?
那么,Id 没有保存在数据库中吗?
Why is Id not the primary key in de DB, if you map it in Hibernate as being the identifier ?
如果在 Hibernate 中将 Id 映射为标识符,为什么 Id 不是 de DB 中的主键?
Why haven't you just put a unique constraint on 'Name' in the database, and create a Primary Key constraint on Id ?
您为什么不在数据库中对 'Name' 设置唯一约束,并在 Id 上创建主键约束?
回答by stista
You should use session.update(object) while you are updating, and session.save(object) while you are saving
您应该在更新时使用 session.update(object),而在保存时使用 session.save(object)
回答by Pascal Thivent
This code always trying insert bill to database , rather than update when row about Bill exists in DB...
此代码总是尝试将帐单插入数据库,而不是在数据库中存在有关帐单的行时进行更新...
From the section 10.7. Automatic state detectionof the Hibernate core documentation:
来自第10.7节。Hibernate 核心文档的自动状态检测:
saveOrUpdate()
does the following:
- if the object is already persistent in this session, do nothing
- if another object associated with the session has the same identifier, throw an exception
- if the object has no identifier property,
save()
it- if the object's identifier has the value assigned to a newly instantiated object,
save()
it- if the object is versioned by a
<version>
or<timestamp>
, and the version property value is the same value assigned to a newly instantiated object,save()
it- otherwise
update()
the object
saveOrUpdate()
执行以下操作:
- 如果该对象已在此会话中持久存在,则不执行任何操作
- 如果与会话关联的另一个对象具有相同的标识符,则抛出异常
- 如果对象没有标识符属性,
save()
它- 如果对象的标识符具有分配给新实例化的对象的值,
save()
则它- 如果对象由
<version>
或 进行 版本控制<timestamp>
,并且版本属性值与分配给新实例化的对象的值相同,save()
则它- 否则
update()
对象
When you do:
当你这样做时:
User bill = new User();
bill.setName("Bill");
session.saveOrUpdate(bill);
This newly created instance does not have any identifier value assigned and saveOrUpdate()
will save()
it, as documented. If this is not what you want, make the name
the primary key.
这个新创建的实例没有分配任何标识符值,并且saveOrUpdate()
会save()
如文档所述。如果这不是您想要的,请制作name
主键。
回答by wallenborn
So you want:
所以你要:
User u1 = new User("Bill");
session.save(u1);
User u2 = new User("Bill");
session.saveOrUpdate(u2);
to notice that u1 and u2 are the same Bill and only store it once? Hibernate has no way of knowing that the Bills are the same person. It only looks at the id of User u2, sees that it's not set, concludes that u2 should be inserted, tries that and reports an exception.
注意到 u1 和 u2 是同一个 Bill 并且只存储一次?Hibernate 无法知道 Bills 是同一个人。它只查看用户 u2 的 id,发现它没有设置,得出应该插入 u2 的结论,尝试并报告异常。
SaveOrUpdate persists both a completely new object and a loaded object that's currently attached to the session. So this works (assuming you have a findByName method somewhere and there's another attribute, let's say favoriteColor):
SaveOrUpdate 保留一个全新的对象和一个当前附加到会话的加载对象。所以这是有效的(假设您在某处有一个 findByName 方法,并且还有另一个属性,假设是最喜爱的颜色):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.saveOrUpdate(u1);
User u2 = findByName("Joe");
u2.setFavoriteColor("red");
session.saveOrUpdate(u2);
But that's not what you want, right?
但这不是你想要的,对吧?
Your problem is made worse by your entity having a surrogate primary key and, separately, a business key (enforced via a uniqueness constraint). If you didn't have an id field and only name as primary key, you could use merge() (for a discussion of saveOrUpdate vs merge, look here):
由于您的实体具有代理主键和单独的业务键(通过唯一性约束强制执行),您的问题变得更糟。如果您没有 id 字段并且只有名称作为主键,则可以使用 merge() (有关 saveOrUpdate 与合并的讨论,请查看此处):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.save(u1);
User u2 = new User("Bill");
u2.setFavoriteColor("red");
u2 = session.merge(u2);
But you don't have that, you need to enforce both the PK constraint on id and the uniqueness on name. So you'll need some variation of merge that does that. Very roughly, you'd like something along these lines:
但是你没有那个,你需要对 id 和名称的唯一性强制执行 PK 约束。所以你需要一些合并的变体来做到这一点。粗略地说,你想要一些类似的东西:
public User mergeByName(User user) {
User merged;
User candidate = findByName(user.getName());
if (candidate != null) {
user.setId(candidate.getId());
merged = session.merge(user);
} else {
session.save(user);
merged = user;
}
return merged;
}
回答by Kartik
First question: If you need to fetch a user named "Bill". How would you do that? That should give you an idea.
第一个问题:如果您需要获取名为“Bill”的用户。你会怎么做?那应该给你一个想法。
To update, you need to have an identity associated with the user object. Having just the name attribute set is not going to help. If you want to update regardless without having the identifier, use HQL as query.
要更新,您需要具有与用户对象关联的身份。仅设置 name 属性无济于事。如果您想在没有标识符的情况下进行更新,请使用 HQL 作为查询。
Query query = session.createQuery("update User u set u.name = :newName where u.name=:name");
query.setString("name", "Bill");
query.setString("newName", "John");
query.executeUpdate();
回答by gauti
If name field is primary key. Then if you set the same name more than once, how it will create new record. ?may be you are not understanding the concept right.
如果名称字段是主键。那么如果多次设置相同的名称,它将如何创建新记录。?可能是你对这个概念的理解不正确。