所以你想要:
User u1 = new User("Bill");
session.save(u1);
User u2 = new User("Bill");
session.saveOrUpdate(u2);
注意到u1和u2是相同的账单,只存储一次?Hibernate无法知道Bills是同一个人。它只查看用户 u2 的 id,看到它未设置,得出应该插入 u2 的结论,尝试并报告异常。
SaveOrUpdate 会保留一个全新的对象和一个当前附加到会话的已加载对象。所以这是有效的(假设你在某处有一个findByName方法,并且有另一个属性,让我们说favoryColor):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.saveOrUpdate(u1);
User u2 = findByName("Joe");
u2.setFavoriteColor("red");
session.saveOrUpdate(u2);
但这不是你想要的,对吧?
由于您的实体具有代理主键和单独的业务键(通过唯一性约束强制执行),您的问题会变得更糟。如果您没有 id 字段,只有名称作为主键,则可以使用 merge() (有关 saveOrUpdate 与 merge 的讨论,请查看此处):
User u1 = new User("Bill");
u1.setFavoriteColor("blue");
session.save(u1);
User u2 = new User("Bill");
u2.setFavoriteColor("red");
u2 = session.merge(u2);
但是你没有这个,你需要对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;
}