2012-01-13 23 views
9

Tôi đang thử nghiệm hibernate và cho truy vấn này đểHibernate merge

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

Và Tôi nhận được những thắc mắc trong dòng lệnh:

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

Tôi đang sử dụng hợp nhất không tiết kiệm, vậy tại sao ngủ đông là cập nhật đối tượng của tôi, Không nên cập nhật. đúng không? Sai lầm là gì?

+1

Liên kết này có thể hữu ích: http://stackoverflow.com/questions/ 161224/what-are-the-different-giữa-the-khác nhau-tiết kiệm-phương pháp-trong-hibernate – Gaurav

Trả lời

22

Tôi sẽ cố gắng giải thích bằng cách sử dụng ví dụ cụ thể hơn. Giả sử bạn có một kịch bản như sau:

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

Ngoại lệ khi cố gắng gắn lại đối tượng được tách rời, userA được tạo.

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. 

Để khắc phục vấn đề trên, sáp nhập() được sử dụng, như hình dưới đây:

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

Có gì là p1 trong session.update (p1); nó là userA? – Elbek

+0

Mỗi 'cuộc hội thoại' (yêu cầu máy khách) 'có thể có tham chiếu' userA' riêng của nó, đúng không? –

0

Do phiên không được đóng và các điều khoản kiên định city đối tượng vẫn được đính kèm với phiên. Vì vậy, bất kỳ thay đổi nào trong đối tượng đó sẽ được lắng nghe bởi phiên ngủ đông và câu lệnh dml thích hợp sẽ được gọi.

+0

đó là đúng nếu tôi sử dụng tiết kiệm() không hợp nhất(). Nếu nó vẫn còn đúng cho hợp nhất thì sự khác nhau giữa lưu và hợp nhất là gì? – Elbek

+1

Hợp nhất rất hữu ích khi bạn có các cá thể tách rời. Trong trường hợp trên, khi bạn đóng phiên, bạn vẫn có đối tượng 'city'. Giả sử, bạn thực hiện một số thay đổi đối tượng 'city' sau khi đóng phiên. Bây giờ một lần nữa bạn mở một phiên và bạn muốn chắc chắn rằng các thay đổi được duy trì. Trong trường hợp này, bạn sẽ sử dụng 'merge' đối tượng city với session và hibernate sẽ đảm bảo các thay đổi được phản ánh trong database. 'save' chủ yếu được sử dụng để duy trì một thực thể và sẽ trả lại mã định danh. – Gaurav

+0

trong trường hợp này mà u mô tả ngay cả tôi có thể sử dụng update() để cập nhật nó. Không cần phải sử dụng kết hợp() :( – Elbek

3

Đó là vấn đề về trình tự. Trên thực tế không phải là một vấn đề. Hibernate đang làm chính xác những gì bạn nói với nó để làm. Như @TejasArjun nói, hợp nhất là về việc sáp nhập dữ liệu bị hủy bỏ. đây là những gì đang diễn ra:

... 
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ôi đã nhờ quan điểm của bạn cho câu trả lời nhưng thậm chí tôi có thể đạt được ở trên bằng cách này: \t \t city.setName ("q"); \t \t \t \t \t \t phiên . = HibernateUtil.getSessionFactory() openSession(); \t \t giao dịch = session.beginTransaction(); \t \t \t \t session.update (thành phố); \t \t \t \t transaction.commit(); Tại sao cần phương thức merge()? Nó là giống nhau – Elbek

+0

Xem ví dụ của tôi về cách sử dụng kết hợp trong câu trả lời thứ hai – Gaurav