2010-05-18 29 views
13

Tôi có một lớp người dùngSử dụng saveOrUpdate() trong Hibernate tạo ra kỷ lục mới thay vì cập nhật những cái hiện có

class User { 
    int id; 
    String name; 
} 

nơi id là máy phát điện có nguồn gốc trong User.hbm.xmlname là khóa chính trong DB.

Trong cơ sở dữ liệu của tôi, tôi đã lưu một số thông tin về Người dùng.

Tôi muốn kết nối với thông tin này về Người dùng.

Ví dụ trong DB của tôi, tôi có một hàng INSERT INTO User VALUES ('Bill');

Main.java

User bill = new User(); 
bill.setName("Bill"); 
session.saveOrUpdate(bill); 

Mã này luôn cố gắng để chèn một Bill hàng mới vào bảng chứ không phải cập nhật các Bill hàng hiện có.

Trả lời

1

Vì vậy, Id không được lưu trong cơ sở dữ liệu?

Tại sao Id không phải là khóa chính trong de DB, nếu bạn ánh xạ nó trong Hibernate làm định danh?

Tại sao bạn không đặt một ràng buộc duy nhất vào 'Tên' trong cơ sở dữ liệu và tạo ràng buộc khóa chính trên Id?

+0

Thx vì sự tin cậy của bạn. 'id' là khóa chính và' name' có constriant độc đáo Chúng tôi có lớp đối tượng Người dùng ví dụ: 'Hóa đơn người dùng = new User()' và thuộc tính về hóa đơn chúng tôi nhận được từ keybord hoặc trang web. : Làm thế nào bạn có thể thực hiện saveOrUpdate() có nghĩa là nếu bill.name tồn tại trong db, chúng tôi gọi update() nếu không chúng tôi lưu hóa đơn. – kunkanwan

-1

Bạn nên sử dụng session.update (object) trong khi bạn đang cập nhật và session.save (object) trong khi bạn đang tiết kiệm

+3

Và 'saveOrUpdate()' có thể làm điều đó cho bạn, đó là điểm của phương pháp này ... –

+0

Vâng, bạn nói đúng nhưng tôi muốn hàm saveOrUpdate() từ hibernate sẽ làm công việc cho tôi. Tôi có thể viết saveOrUpdate() của tôi, nơi tôi kiểm tra chọn nếu 'name' tồn tại trong db và gọi save() hoặc update(). Tôi nghĩ rằng nó không phải là ý tưởng tốt, và có lẽ hibernate có giải pháp tốt hơn cho ví dụ ghi đè bằng(), nơi chúng tôi so sánh các yếu tố từ khóa bussines. – kunkanwan

27

Mã này luôn cố gắng hóa đơn chèn cơ sở dữ liệu, chứ không phải là bản cập nhật khi hàng về Bill tồn tại trong DB ...

Từ phần 10.7. Automatic state detection các tài liệu cốt lõi Hibernate:

saveOrUpdate() nào sau đây:

  • nếu đối tượng đã dai dẳng trong phiên này, không làm gì cả
  • nếu một đối tượng khác được liên kết với phiên có cùng số nhận dạng, hãy ném một ví dụ ception
  • nếu đối tượng không có tài sản định danh, save()
  • nếu nhận dạng của đối tượng có giá trị gán cho một mới khởi tạo đối tượng, save()
  • nếu đối tượng được là phiên bản của một <version> hoặc <timestamp> và phiên bản giá trị thuộc tính có cùng giá trị được gán cho đối tượng mới được khởi tạo, save()
  • khác update() đối tượng

Khi bạn làm:

User bill = new User(); 
bill.setName("Bill"); 
session.saveOrUpdate(bill); 

dụ mới được tạo ra này không có bất kỳ giá trị định danh giao và saveOrUpdate() sẽ save() nó, như tài liệu. Nếu đây không phải là điều bạn muốn, hãy tạo name khóa chính.

+0

Thx vì sự tin tưởng của bạn, tôi thấy lý do tại sao chương trình của tôi luôn cố gắng chèn. Làm thế nào tôi có thể làm điều đó mà không làm cho tên khóa chính vì tôi có id đó là nhanh hơn và dễ dàng hơn. Tôi có thể làm điều đó bằng cách sử dụng thêm lựa chọn như thế: 'User bill = new User(); bill.setName ("Bill"); bill.setId (func()); 'trong đó func() là một hàm kết quả là null khi hàng có' name = 'Bill'' không tồn tại nếu không trả về số id của hàng này; Làm thế nào tôi có thể làm điều đó mà không cần chọn? Làm thế nào giải quyết vấn đề này Pro Developer? – kunkanwan

+0

@kunkanwan: Tôi không chắc làm cách nào tôi nên hiểu "nhà phát triển chuyên nghiệp" này. Ngay bây giờ, điều này không thúc đẩy tôi giúp bạn thêm. –

+0

Tôi e rằng bạn không hiểu tôi. Tiếng Anh của tôi yếu lắm. Trong câu 'Pro developer' tôi muốn biết cách giải quyết vấn đề này trong ngành công nghiệp phần mềm (tôi là sinh viên không có kinh nghiệm), nơi chức năng đơn giản của tôi với lựa chọn thêm là không đủ tốt. Tôi xin lỗi nếu tôi làm tổn thương bạn. – kunkanwan

14

Vì vậy, bạn muốn:

User u1 = new User("Bill"); 
session.save(u1); 
User u2 = new User("Bill"); 
session.saveOrUpdate(u2); 

để nhận thấy rằng u1 và u2 đều giống nhau Bill và chỉ lưu trữ nó một lần? Hibernate không có cách nào để biết rằng Bills là cùng một người. Nó chỉ nhìn vào id của User u2, thấy rằng nó không được thiết lập, kết luận rằng u2 nên được chèn vào, cố gắng và báo cáo một ngoại lệ.

SaveOrUpdate vẫn tồn tại cả đối tượng hoàn toàn mới và đối tượng được tải hiện được đính kèm với phiên. Vì vậy, các công trình này (giả sử bạn có một phương pháp findByName đâu đó và có thuộc tính khác, giả sử favoriteColor):

User u1 = new User("Bill"); 
u1.setFavoriteColor("blue"); 
session.saveOrUpdate(u1); 
User u2 = findByName("Joe"); 
u2.setFavoriteColor("red"); 
session.saveOrUpdate(u2); 

Nhưng đó không phải là những gì bạn muốn, phải không?

Vấn đề của bạn được thực hiện tồi tệ hơn bởi thực thể của bạn có khóa chính thay thế và, riêng biệt, khóa doanh nghiệp (được thực thi thông qua ràng buộc duy nhất). Nếu bạn không có một trường id và chỉ đặt tên là khóa chính, bạn có thể sử dụng kết hợp() (cho một cuộc thảo luận về saveOrUpdate vs merge, look here):

User u1 = new User("Bill"); 
u1.setFavoriteColor("blue"); 
session.save(u1); 
User u2 = new User("Bill"); 
u2.setFavoriteColor("red"); 
u2 = session.merge(u2); 

Nhưng bạn không có điều đó, bạn cần phải thực thi cả ràng buộc PK trên id và tính duy nhất trên tên. Vì vậy, bạn sẽ cần một số biến thể của hợp nhất mà làm điều đó.Rất gần, bạn muốn một cái gì đó dọc theo các dòng sau:

public User mergeByName(User user) { 
    User merged; 
    User candidate = findByName(user.getName()); 
    if (candidate != null) { 
     user.setId(candidate.getId()); 
     merged = session.merge(user); 
    } else { 
     session.save(user); 
     merged = user; 
    } 
    return merged; 
} 
1

Câu hỏi đầu tiên: Nếu bạn cần tìm nạp người dùng có tên "Bill". Bạn làm điều đó như thế nào? Điều đó sẽ cho bạn một ý tưởng.

Để cập nhật, bạn cần có một danh tính được liên kết với đối tượng người dùng. Chỉ có tập thuộc tính tên sẽ không giúp được gì. Nếu bạn muốn cập nhật bất kể mà không có mã định danh, hãy sử dụng HQL làm truy vấn.

Query query = session.createQuery("update User u set u.name = :newName where u.name=:name"); 
query.setString("name", "Bill"); 
query.setString("newName", "John"); 
query.executeUpdate(); 
-3

Nếu trường tên là khóa chính. Sau đó, nếu bạn đặt cùng một tên nhiều lần, cách nó sẽ tạo bản ghi mới. ? có thể là bạn không hiểu khái niệm đúng.

Các vấn đề liên quan