2012-01-13 16 views
9

jestem testowania hibernacji i daje to zapytanie doHibernate scalić

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

A ja uzyskanie tych zapytań w linii poleceń:

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

używam scalania nie oszczędzać, więc dlaczego hibernacji jest aktualizowanie mojego obiektu, nie powinno się aktualizować. czy to prawda? Co to za błąd?

+1

To połączenie może być przydatne: http://stackoverflow.com/questions/ 161224/jakie są różnice między różnymi metodami zapisu w hibernacji – Gaurav

Odpowiedz

22

Spróbuję wyjaśnić za pomocą bardziej konkretnego przykładu. Załóżmy, że masz scenariusz taki jak poniżej:

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

Wyjątek w przypadku próby ponownego przyłączenia obiektu wolnostojącego, 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. 

Aby obejść powyższego problemu, łączenia() stosuje się, jak to pokazano poniżej:

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

Co to jest p1 w session.update (p1); czy to jest userA? – Elbek

+0

Każda "konwersacja" (żądanie klienta) 'może mieć własne odwołanie' userA', tak? –

0

Sesja nie jest jeszcze zamknięta, a w przypadku trwałości obiekt jest nadal przyłączony do sesji. Tak więc wszelkie zmiany w tym obiekcie będą odsłuchiwane przez sesję hibernacji, a odpowiednie polecenie dml zostanie wywołane.

+0

, które są poprawne, jeśli użyję funkcji save() not mergge(). Jeśli nadal jest w porządku dla scalenia, jaka jest różnica między zapisem a scalaniem? – Elbek

+1

Scalanie jest przydatne, gdy masz odłączone instancje. W powyższym przypadku po zamknięciu sesji nadal znajduje się obiekt 'city'. Załóżmy, że wprowadzasz pewne zmiany do obiektu 'city' po zamknięciu sesji. Teraz ponownie otwierasz sesję i chcesz się upewnić, że zmiany są zachowane. W takim przypadku użyjesz 'scalania 'obiektu miasta z sesją, a stan hibernacji sprawi, że zmiany zostaną odzwierciedlone w bazie danych. 'save' służy przede wszystkim do zachowania jednostki i zwróci identyfikator. – Gaurav

+0

w tym przypadku, który opisałem nawet i mogę użyć update(), aby go zaktualizować. nie ma potrzeby korzystania seryjnej() :( – Elbek

3

To jest kolejność problemu. Właściwie to nie problem. Hibernate robi dokładnie to, co kazałeś mu zrobić. Jak mówi @TejasArjun, scalanie polega na łączeniu się w deteched danych. o to, co się dzieje:

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

mam swój punkt dzięki za odpowiedź, ale jeszcze mogę osiągnąć powyższe w ten sposób: \t \t city.setName („Q”); \t \t \t \t \t \t sesji . = HibernateUtil.getSessionFactory() openSession(); \t \t transakcji = session.beginTransaction(); \t \t \t \t session.update (Miasto) \t \t \t \t transaction.commit(); Dlaczego więc potrzebujesz metody merge()? Jest to ten sam – Elbek

+0

Zobacz mój przykład użycia scalania w drugiej odpowiedzi – Gaurav