2012-01-13 10 views
9

estoy probando hibernación y dando a esta consulta paraHibernate fusionar

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

Y me estoy haciendo esas consultas en la línea de comandos:

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

estoy usando mezcla no ahorrar, así que por qué hibernación es actualizando mi objeto, no debería actualizarse ¿está bien? ¿Cuál es el error?

+1

Este enlace puede ser útil: http://stackoverflow.com/questions/ 161224/what-are-the-differences-between-the-different-saving-methods-in-hibernate – Gaurav

Respuesta

22

Trataré de explicarlo utilizando un ejemplo más concreto. Suponga que tiene un escenario, como a continuación:

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

excepción cuando, se hace un intento de volver a colocar un objeto independiente 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. 

Para evitar el problema anterior, fusionar() se utiliza, como se muestra a continuación:

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

WHat es p1 en session.update (p1); ¿es userA? – Elbek

+0

Cada ''conversación' (solicitud del cliente)' puede tener su propia referencia 'userA', ¿sí? –

0

Debido a que la sesión aún no está cerrada y en términos de persistencia city el objeto aún está adjunto a la sesión. Entonces, cualquier cambio en ese objeto será escuchado por la sesión de hibernación y se invocará la declaración de dml apropiada.

+0

que es correcto si uso save() not merge(). Si todavía está correcto fusionar, ¿cuál es la diferencia entre guardar y fusionar? – Elbek

+1

Merge es útil cuando tiene instancias separadas. En el caso anterior, cuando cierra la sesión todavía tiene el objeto 'ciudad'. Supongamos que realiza algunos cambios al objeto 'ciudad' después de cerrar la sesión. Ahora nuevamente abre una sesión y desea asegurarse de que los cambios se mantengan. En este caso, utilizará 'merge' el objeto de la ciudad con la sesión e hibernate se asegurará de que los cambios se reflejen en la base de datos. 'save' se usa principalmente para persistir una entidad y devolver el identificador. – Gaurav

+0

en este caso que describió incluso puedo usar update() para actualizarlo. no hay necesidad de utilizar la combinación de() :( – Elbek

3

Es un problema de secuencia. En realidad no es un problema. Hibernate está haciendo exactamente lo que le pediste que hiciera. Como dice @TejasArjun, fusionar se trata de fusionarse en datos ocultos. esto es lo que está pasando:

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

me dieron su punto de gracias por la respuesta, pero hasta yo puedo llegar a la anterior de esta manera: \t \t city.setName ("q"); \t \t \t \t \t \t sesión . = HibernateUtil.getSessionFactory() openSession(); \t \t transacción = session.beginTransaction(); \t \t \t \t session.update (ciudad); \t \t \t \t transaction.commit(); ¿Por qué entonces necesita el método merge()? Es el mismo – Elbek

+0

Vea mi ejemplo sobre el uso de fusión en la segunda respuesta – Gaurav