【问题标题】:Hibernate merge休眠合并
【发布时间】:2012-02-09 09:18:15
【问题描述】:

我正在测试休眠并将此查询提供给

transaction = session.beginTransaction();
city = new City("A");
city  = (City)session.merge(city);
city.setName("B");
transaction.commit();

我在命令行中得到这些查询:

Hibernate: insert into CITY (name) values (?)
Hibernate: update CITY set name=? where CITY_ID=?

我使用的是合并而不是保存,所以为什么休眠更新我的对象,它不应该更新。对吗?什么错误?

【问题讨论】:

标签: java hibernate


【解决方案1】:

我将尝试使用更具体的示例进行解释。假设您有如下场景:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
User userA = (User)session.get(User.class, 1101);
transaction.commit();
session.close();
// Since session is closed, userA is detached.

session = sessionFactory.openSession();
transaction = session.beginTransaction();
User userB = (User)session.get(User.class, 1101);
//Now here,  userB represents the same persistent row as userA.
//When an attempt to reattach userA occurs, an exception is thrown
session.update(userA);
transaction.commit();
session.close();

尝试重新附加已分离对象时出现异常,userA。

Exception in thread "main" org.hibernate.NonUniqueObjectException: a   
different object with the same identifier value was already associated
with the session:

This is because Hibernate is enforcing that only a single instance of a Persistent    object exists in memory.

为了解决上述问题,使用了merge(),如下所示:

Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
User userA = (User)session.get(User.class, 1101);
transaction.commit();
session.close();
//userA is now detached as session is closed.

session = sessionFactory.openSession();
transaction = session.beginTransaction();
User userB = (User)session.get(User.class, 1101);
User userC = (User)session.merge(userA);
if (userB == userC) {
  System.out.println("Reattched user is equal");
}
transaction.commit();
session.close();

【讨论】:

  • 每个'conversation' (client request) 都可以有自己的userA 引用,是吗?
【解决方案2】:

这是一个排序问题。其实不是问题。 Hibernate 正在做你告诉它做的事情。正如@TejasArjun 所说,合并是关于合并去技术数据。这是发生了什么:

...
city  = (City)session.merge(city); 
// No different to save(). Hibernate schedules an insert to the
// database to store the current record.

city.setName("B"); 
// The object is now flagged as dirty and needing to be saved. 
// Hiberate automatically tracks properties on objects and knows when they change.

transaction.commit(); 
// Hibernate sees that 'city' has been changed since it was saved, 
// so it schedules an update to store the new data.

【讨论】:

  • 感谢您的回答,我明白了你的意思,但即使我可以通过这种方式达到上述目的:city.setName("q"); session = HibernateUtil.getSessionFactory().openSession();事务 = session.beginTransaction(); session.update(城市);事务.commit();那么为什么需要merge() 方法呢?是一样的
  • 查看我在第二个答案中使用合并的示例
【解决方案3】:

因为会话尚未关闭,并且在持久性方面city 对象仍附加到会话。因此,该对象中的任何更改都将被休眠会话监听并调用适当的 dml 语句。

【讨论】:

  • 如果我使用 save() 而不是 merge() 是正确的。如果仍然适合合并,那么保存和合并有什么区别?
  • 当您有分离的实例时,合并很有用。在上述情况下,当您关闭会话时,您仍然拥有city 对象。假设您在关闭会话后对city 对象进行了一些更改。现在您再次打开一个会话,并且您希望确保更改保持不变。在这种情况下,您将在会话中使用merge 城市对象,并且休眠将确保更改反映在数据库中。 save 主要用于持久化实体并返回标识符。
  • 在这种情况下,你描述了即使我可以使用 update() 来更新它。无需使用 merge() :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多