简体   繁体   中英

Hibernate merge

I am testing hibernate and giving this query to

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

And I am getting those queries in the command line:

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

I am using merge not save, so why hibernate is updating my object, It should not update. am it right? What is the mistake?

I will try to explain using a more concrete example. Suppose you have a scenario like below :

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

Exception when an attempt to reattach a Detached object, userA is made.

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.

To get around the above problem, merge() is used, as shown below :

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

It's a sequencing issue. Actually not an issue. Hibernate is doing exactly what you told it to do. As @TejasArjun says, merge is about merging in deteched data. here's what is going on:

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

Because session is not closed yet and in persistence terms city object is still attached to session. So, any changes in that object will be listened by hibernate session and appropriate dml statement will be invoked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM