2011-06-22 25 views
38

Có ai biết làm thế nào Hibernate biết có nên INSERT hoặc UPDATE một giá trị trong cơ sở dữ liệu khi session.saveOrUpdate() được gọi?Hibernate saveOrUpdate behavior

Cho đến nay, tôi chỉ xác định rằng nó không phụ thuộc vào thông tin trong bộ nhớ cache và rằng sự tồn tại của thực thể trong cơ sở dữ liệu được xác định bằng khóa chính.

Trả lời

37

Khi bạn sử dụng .saveOrUpdate() Hibernate sẽ kiểm tra xem đối tượng có tạm thời không. Nếu đối tượng có một số nhận dạng thì nó sẽ thực hiện .update().

Từ documentation:

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 liên quan đến phiên có cùng một số nhận dạng, ném một ngoại lệ
  • nếu đối tượng không có số nhận dạng thuộc tính, hãy lưu() nó
  • nếu nhận dạng của đối tượng có giá trị gán cho một đối tượng khởi tạo mới , tiết kiệm() nó
  • nếu đối tượng đang là phiên bản của một hay, và phiên bản giá trị tài sản là cùng một giá trị giao cho một đối tượng instantiated mới , lưu() nó nếu không cập nhật() đối tượng
+1

"nếu nhận dạng của đối tượng có giá trị được gán cho một đối tượng mới được khởi tạo, tiết kiệm()" Tôi tạo ra một 'bản sao() 'của một đối tượng tách rời (giữ cùng số nhận dạng) và sửa đổi một giá trị. Hibernate 'update()' đối tượng. thuộc loại nào nó rơi? – iliaden

+0

Xin lỗi, đã sửa câu trả lời của tôi với định dạng đúng. Tôi đoán dưới "nếu một đối tượng khác liên kết với phiên có cùng số nhận dạng, hãy ném một ngoại lệ"?! – Rihards

+0

Tôi không nhận được bất kỳ ngoại lệ nào, vì đối tượng đầu tiên được tách ra thông qua 'session.evict()'. – iliaden

1

Điều này được thực hiện dựa trên giá trị của khóa chính. Nếu khóa chính không được xác định, giá trị của nó sẽ mặc định là 0 cho các phím thay thế số và save sẽ được thực hiện. Nếu khóa chính được điền, nó sẽ gọi một số update.

+0

Điều này không đúng, đối với tôi saveOrUpdate không cập nhật ngay cả khi tôi cung cấp bản cập nhật có cùng khóa chính. – Siddharth

+0

@Siddharth: Thật khó để biết vấn đề gì trong mã của bạn không thấy mã. Tôi đã sử dụng Hibernate 8 năm nay và saveOrUpdate đã làm việc tốt cho tôi. – Olaf

+0

Tôi chỉ có thể làm cho nó hoạt động với các thuộc tính update = true, insert = false trong hbm. – Siddharth

2

Như đã nêu here, saveOrUpdate hoặc lưu một phiên bản tạm thời bằng cách tạo số nhận dạng mới hoặc cập nhật/reattaches các cá thể tách rời được liên kết với số nhận dạng hiện tại của nó.Cụ thể hơn nó:

  • nếu đối tượng đã liên tục trong phiên này, không làm gì cả
  • nếu một đối tượng liên quan đến phiên có nhận dạng thì ném một ngoại lệ
  • nếu đối tượng không có định danh bất động sản, save()
  • nếu nhận dạng của đối tượng có giá trị được gán cho một đối tượng mới được khởi tạo, tiết kiệm() nó
  • nếu đối tượng đang là phiên bản của một <version> hoặc <timestamp>, và phiên bản giá trị tài sản là
  • cùng giá trị được gán cho một đối tượng mới được khởi tạo, save()
  • khác update() đối tượng
9

Có lẽ nó là hữu ích để trích dẫn Hibernate kinh thánh (Java Persistence with Hibernate, 2nd ed., trang 528):

Người dùng Hibernate có kinh nghiệm hơn chỉ sử dụng saveOrUpdate(); nó dễ dàng hơn nhiều để cho Hibernate quyết định cái gì mới và cái gì là cũ, đặc biệt là trong một mạng lưới các đối tượng phức tạp hơn với trạng thái hỗn hợp. Nhược điểm duy nhất (không thực sự nghiêm trọng) của độc quyền saveOrUpdate() là đôi khi không thể đoán được một cá thể là cũ hay mới mà không bắn một số SELECT tại cơ sở dữ liệu - ví dụ, khi một lớp được ánh xạ với một khóa tổng hợp tự nhiên và không có phiên bản hoặc thuộc tính dấu thời gian.

Hibernate phát hiện các phiên bản nào cũ và mới là gì? Một loạt các tùy chọn có sẵn. Hibernate giả định rằng một cá thể là một cá thể tạm thời chưa được lưu nếu:

  • Đặc tính nhận dạng là null.
  • Thuộc tính phiên bản hoặc dấu thời gian (nếu tồn tại) là null.
  • Một phiên bản mới của cùng một lớp liên tục, được tạo bởi Hibernate trong nội bộ, có cùng giá trị số nhận dạng cơ sở dữ liệu như trường hợp đã cho.
  • Bạn cung cấp unsaved-value trong tài liệu ánh xạ cho lớp và giá trị của thuộc tính số nhận dạng phù hợp. Thuộc tính unsaved-value cũng có sẵn cho các phần tử ánh xạ phiên bản và dấu thời gian.
  • Dữ liệu thực thể có cùng giá trị số nhận dạng không nằm trong bộ nhớ cache cấp thứ hai.
  • Bạn cung cấp triển khai hoặc org.hibernate.Interceptor và trả lại Boolean.TRUE từ Interceptor.isUnsaved() sau khi kiểm tra cá thể trong mã của bạn.
+2

Quét tài liệu không thể đọc được trên màn hình hoặc có thể tìm kiếm được. –

1

Nếu ai đó không thực sự hiểu về mặt lý thuyết thì có một mã

 MyModel sent = myDao.myDaoImpl(id);     
    if(sent == null){      
     sent = **new MyModel();** // new Object 
     sent.setXX(id); 
     sent.setYY("Yes"); 
     sent.setDate(new Date()); 
     myDao.saveOrUpdate(sent); // Insert will be called 
    }else if(! "Yes".equalsIgnoreCase(sent.getFlag())){ 
     sent.setXX("Yes"); 
     sent.setDate(new Date()); 
     myDao.saveOrUpdate(sent); // Update will be called 
    } 
Các vấn đề liên quan