2012-01-13 140 views
9

我测试休眠,并给予该查询休眠合并

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

我使用合并不救,为什么Hibernate是更新我的对象,它不应该更新。它是正确的吗?什么是错误?

+1

该链接可能是有用的: http://stackoverflow.com/questions/ 161224 /如果我使用save()不合并(),那么这是正确的,这是不同的节能方法之间的区别在休眠 – Gaurav 2012-01-13 05:04:57

回答

22

我会尽量用一个更具体的例子来解释。假设您的场景如下所示:

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

尝试重新挂接Detached对象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. 

为了解决上述问题,合并()时,如下图所示:

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(); 
+0

什么是p1在session.update(p1);它是userA吗? – Elbek 2012-01-13 05:28:48

+0

每个“对话”(客户端请求)'都可以有自己的'userA'引用,是吗? – 2013-12-15 18:44:38

0

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

+0

。如果它仍然适合合并,那么保存和合并有什么区别? – Elbek 2012-01-13 04:51:34

+1

当您有分离的实例时,合并很有用。在上面的例子中,当你关闭会话时,你仍然有'city'对象。假设您在关闭会话后对“城市”对象进行了一些更改。现在再次打开一个会话,并且要确保所做的更改保持不变。在这种情况下,您可以使用合并城市对象与会话,并且hibernate将确保更改反映在数据库中。 'save'主要用于坚持一个实体并且会返回标识符。 – Gaurav 2012-01-13 04:55:44

+0

在这种情况下,你甚至可以使用update()来更新它。没有必要使用合并():( – Elbek 2012-01-13 05:05:19

3

这是一个测序问题。其实不是问题。 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. 
+0

我得到的回答你的观点感谢,但连我可以通过这种方式达到以上:\t \t city.setName(“Q”); \t \t \t \t \t \t会议= HibernateUtil.getSessionFactory()的openSession(); \t \t交易= session.beginTransaction(); \t \t \t \t了session.update(城市); \t \t \t \t transaction.commit(); 为什么然后需要merge()方法?这是相同的 – Elbek 2012-01-13 05:21:51

+0

请参阅我的示例在第二个答案中使用合并 – Gaurav 2012-01-13 05:26:27