EntityManager.merge()
có thể chèn các đối tượng mới và cập nhật những đối tượng hiện có.
Tại sao một người muốn sử dụng persist()
(chỉ có thể tạo các đối tượng mới)?
EntityManager.merge()
có thể chèn các đối tượng mới và cập nhật những đối tượng hiện có.
Tại sao một người muốn sử dụng persist()
(chỉ có thể tạo các đối tượng mới)?
Câu trả lời:
Dù bằng cách nào cũng sẽ thêm một thực thể vào PersistenceContext, sự khác biệt là ở những gì bạn làm với thực thể sau đó.
Persist lấy một thực thể, thêm nó vào ngữ cảnh và làm cho cá thể đó được quản lý (tức là các cập nhật trong tương lai cho thực thể sẽ được theo dõi).
Hợp nhất trả về thể hiện được quản lý mà trạng thái được hợp nhất. Nó trả về một cái gì đó tồn tại trong PersistenceContext hoặc tạo một thể hiện mới của thực thể của bạn. Trong mọi trường hợp, nó sẽ sao chép trạng thái từ thực thể được cung cấp và trả về bản sao được quản lý. Trường hợp bạn chuyển vào sẽ không được quản lý (mọi thay đổi bạn thực hiện sẽ không phải là một phần của giao dịch - trừ khi bạn gọi lại hợp nhất). Bạn có thể thông qua việc sử dụng thể hiện trả lại (được quản lý).
Có lẽ một ví dụ mã sẽ giúp.
MyEntity e = new MyEntity();
// scenario 1
// tran starts
em.persist(e);
e.setSomeField(someValue);
// tran ends, and the row for someField is updated in the database
// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue);
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)
// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue);
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)
Kịch bản 1 và 3 tương đương nhau, nhưng có một số tình huống bạn muốn sử dụng Kịch bản 2.
merge
bản sao đầy đủ của một đối tượng trước khi quản lý nó có hiệu năng?
@GeneratedId
thể lấy nó trong kịch bản 2 không?
Kiên trì và hợp nhất là cho hai mục đích khác nhau (chúng không phải là sự thay thế nào cả).
(chỉnh sửa để mở rộng thông tin khác biệt)
kiên trì:
hợp nhất:
hiệu quả ()
kiên trì () ngữ nghĩa:
Thí dụ:
{
AnyEntity newEntity;
AnyEntity nonAttachedEntity;
AnyEntity attachedEntity;
// Create a new entity and persist it
newEntity = new AnyEntity();
em.persist(newEntity);
// Save 1 to the database at next flush
newEntity.setValue(1);
// Create a new entity with the same Id than the persisted one.
AnyEntity nonAttachedEntity = new AnyEntity();
nonAttachedEntity.setId(newEntity.getId());
// Save 2 to the database at next flush instead of 1!!!
nonAttachedEntity.setValue(2);
attachedEntity = em.merge(nonAttachedEntity);
// This condition returns true
// merge has found the already attached object (newEntity) and returns it.
if(attachedEntity==newEntity) {
System.out.print("They are the same object!");
}
// Set 3 to value
attachedEntity.setValue(3);
// Really, now both are the same object. Prints 3
System.out.println(newEntity.getValue());
// Modify the un attached object has no effect to the entity manager
// nor to the other objects
nonAttachedEntity.setValue(42);
}
Cách này chỉ tồn tại 1 đối tượng đính kèm cho bất kỳ đăng ký nào trong trình quản lý thực thể.
merge () cho một thực thể với id là một cái gì đó như:
AnyEntity myMerge(AnyEntity entityToSave) {
AnyEntity attached = em.find(AnyEntity.class, entityToSave.getId());
if(attached==null) {
attached = new AnyEntity();
em.persist(attached);
}
BeanUtils.copyProperties(attached, entityToSave);
return attached;
}
Mặc dù nếu được kết nối với MySQL merge () có thể hiệu quả như vẫn tồn tại () bằng cách sử dụng lệnh gọi tới INSERT với tùy chọn ON DUPLICATE KEY UPDATE, JPA là một chương trình cấp cao và bạn không thể cho rằng điều này sẽ xảy ra ở mọi nơi.
em.persist(x)
với x = em.merge(x)
?
merge()
cũng có thể némEntityExistsException
RuntimeException
, nhưng nó không được đề cập trong Javadoc.
Nếu bạn đang sử dụng trình tạo được chỉ định, sử dụng hợp nhất thay vì liên tục có thể gây ra câu lệnh SQL dư thừa , do đó ảnh hưởng đến hiệu suất.
Ngoài ra, gọi hợp nhất cho các thực thể được quản lý cũng là một sai lầm vì các thực thể được quản lý được quản lý tự động bởi Hibernate và trạng thái của chúng được đồng bộ hóa với bản ghi cơ sở dữ liệu bằng cơ chế kiểm tra bẩn khi xóa Bối cảnh liên tục .
Để hiểu cách thức hoạt động của tất cả những điều này, trước tiên bạn nên biết rằng Hibernate chuyển tư duy của nhà phát triển từ các câu lệnh SQL sang các chuyển đổi trạng thái thực thể .
Khi một thực thể được Hibernate quản lý tích cực, tất cả các thay đổi sẽ được tự động truyền tới cơ sở dữ liệu.
Màn hình ngủ đông hiện đang gắn liền với các thực thể. Nhưng để một thực thể trở nên được quản lý, nó phải ở trạng thái thực thể phù hợp.
Để hiểu rõ hơn về chuyển đổi trạng thái JPA, bạn có thể hình dung sơ đồ sau:
Hoặc nếu bạn sử dụng API cụ thể Hibernate:
Như được minh họa bởi các sơ đồ trên, một thực thể có thể ở một trong bốn trạng thái sau:
Mới (thoáng qua)
Một đối tượng mới được tạo chưa từng được liên kết với Hibernate Session
(aka Persistence Context
) và không được ánh xạ tới bất kỳ hàng trong bảng cơ sở dữ liệu nào được coi là ở trạng thái Mới (Tạm thời).
Để trở nên bền bỉ, chúng ta cần gọi EntityManager#persist
phương thức một cách rõ ràng hoặc sử dụng cơ chế duy trì bắc cầu.
Kiên trì (Quản lý)
Một thực thể liên tục đã được liên kết với một hàng của bảng cơ sở dữ liệu và nó được quản lý bởi Bối cảnh liên tục hiện đang chạy. Bất kỳ thay đổi nào được thực hiện cho một thực thể như vậy sẽ được phát hiện và lan truyền đến cơ sở dữ liệu (trong thời gian tuôn ra Phiên). Với Hibernate, chúng ta không còn phải thực thi các câu lệnh INSERT / UPDATE / DELETE. Hibernate sử dụng một phong cách làm việc đằng sau giao dịch và các thay đổi được đồng bộ hóa tại thời điểm chịu trách nhiệm cuối cùng, trong thời gian Session
xả hiện tại .
Tách rời
Khi Bối cảnh liên tục hiện đang chạy, tất cả các thực thể được quản lý trước đó sẽ bị tách ra. Những thay đổi kế tiếp sẽ không còn được theo dõi và sẽ không xảy ra đồng bộ hóa cơ sở dữ liệu tự động.
Để liên kết một thực thể tách rời với Phiên Hibernate đang hoạt động, bạn có thể chọn một trong các tùy chọn sau:
Gắn lại
Hibernate (nhưng không phải JPA 2.1) hỗ trợ gắn lại thông qua phương thức cập nhật Phiên #. Phiên Hibernate chỉ có thể liên kết một đối tượng Thực thể cho một hàng cơ sở dữ liệu đã cho. Điều này là do Bối cảnh liên tục hoạt động như một bộ đệm trong bộ nhớ (bộ đệm cấp đầu tiên) và chỉ có một giá trị (thực thể) được liên kết với một khóa nhất định (loại thực thể và định danh cơ sở dữ liệu). Một thực thể chỉ có thể được gắn lại nếu không có đối tượng JVM khác (khớp với cùng một hàng cơ sở dữ liệu) đã được liên kết với Phiên Hibernate hiện tại.
Sáp nhập
Việc hợp nhất sẽ sao chép trạng thái thực thể tách rời (nguồn) sang một thực thể được quản lý (đích). Nếu thực thể hợp nhất không có tương đương trong Phiên hiện tại, một thực thể sẽ được tìm nạp từ cơ sở dữ liệu. Đối tượng được tách ra sẽ tiếp tục được tách ra ngay cả sau khi hoạt động hợp nhất.
Đã xóa
Mặc dù JPA yêu cầu các thực thể được quản lý chỉ được phép xóa, Hibernate cũng có thể xóa các thực thể tách rời (nhưng chỉ thông qua lệnh gọi phương thức xóa Phiên #). Một thực thể bị xóa chỉ được lên lịch để xóa và câu lệnh XÓA cơ sở dữ liệu thực tế sẽ được thực thi trong thời gian xả phiên.
Tôi nhận thấy rằng khi tôi sử dụng em.merge
, tôi nhận được một SELECT
tuyên bố cho mọi người INSERT
, ngay cả khi không có trường nào mà JPA đang tạo cho tôi - trường khóa chính là UUID do tôi tự đặt. Tôi chuyển sang em.persist(myEntityObject)
và chỉ nhận được INSERT
báo cáo sau đó.
merge()
. Tôi đã có cơ sở dữ liệu PostgreSQL với chế độ xem phức tạp : chế độ xem tổng hợp dữ liệu từ một số bảng (các bảng có cấu trúc giống hệt nhau nhưng tên khác nhau). Vì vậy, JPA đã cố gắng thực hiện merge()
, nhưng thực tế JPA đã tạo trước tiên SELECT
(cơ sở dữ liệu do cài đặt chế độ xem có thể trả về một số bản ghi có cùng khóa chính từ các bảng khác nhau!), Sau đó JPA (Hibernate là một triển khai) đã thất bại: có một số bản ghi có cùng khóa ( org.hibernate.HibernateException: More than one row with the given identifier was found
). Trong trường hợp của tôi persist()
đã giúp tôi.
Các đặc điểm kỹ thuật JPA nói sau đây về persist()
.
Nếu X là một đối tượng tách rời,
EntityExistsException
có thể được ném khi hoạt động bền bỉ được gọi, hoặcEntityExistsException
hoặc một đối tượng khácPersistenceException
có thể được ném vào lúc xả hoặc cam kết.
Vì vậy, việc sử dụng persist()
sẽ phù hợp khi đối tượng không phải là một đối tượng tách rời. Bạn có thể muốn có mã ném PersistenceException
để nó thất bại nhanh chóng.
Mặc dù thông số kỹ thuật không rõ ràng , nhưng persist()
có thể đặt @GeneratedValue
@Id
cho một đối tượng. merge()
tuy nhiên phải có một đối tượng với @Id
đã được tạo.
merge()
tuy nhiên phải có một đối tượng với @Id
đã được tạo . ". Bất cứ khi nào EntityManager không tìm thấy giá trị cho trường của ID đối tượng, nó vẫn tồn tại (được chèn) vào DB.
Một số chi tiết khác về hợp nhất sẽ giúp bạn sử dụng hợp nhất trên liên tục:
Trả về một thể hiện được quản lý khác với thực thể ban đầu là một phần quan trọng của quy trình hợp nhất. Nếu một thực thể có cùng định danh đã tồn tại trong ngữ cảnh bền vững, nhà cung cấp sẽ ghi đè trạng thái của nó với trạng thái của thực thể được hợp nhất, nhưng phiên bản được quản lý tồn tại phải được trả về cho khách hàng để có thể được trả về đã sử dụng. Nếu nhà cung cấp không cập nhật phiên bản Nhân viên trong ngữ cảnh liên tục, mọi tham chiếu đến trường hợp đó sẽ trở nên không nhất quán với trạng thái mới được sáp nhập.
Khi merge () được gọi trên một thực thể mới, nó hoạt động tương tự như hoạt động bền vững (). Nó thêm thực thể vào bối cảnh bền vững, nhưng thay vì thêm thể hiện thực thể ban đầu, nó tạo ra một bản sao mới và thay vào đó quản lý thể hiện đó. Bản sao được tạo bởi hoạt động merge () được duy trì như thể phương thức contin () được gọi trên nó.
Khi có các mối quan hệ, hoạt động merge () sẽ cố gắng cập nhật thực thể được quản lý để trỏ đến các phiên bản được quản lý của các thực thể được tham chiếu bởi thực thể tách rời. Nếu thực thể có mối quan hệ với một đối tượng không có danh tính liên tục, kết quả của hoạt động hợp nhất là không xác định. Một số nhà cung cấp có thể cho phép bản sao được quản lý trỏ đến đối tượng không liên tục, trong khi những nhà cung cấp khác có thể ném ngoại lệ ngay lập tức. Hoạt động hợp nhất () có thể được xếp tầng tùy ý trong các trường hợp này để ngăn chặn ngoại lệ xảy ra. Chúng tôi sẽ đề cập đến tầng của hoạt động merge () sau trong phần này. Nếu một thực thể được hợp nhất trỏ đến một thực thể bị xóa, một ngoại lệ IllegalArgumentException sẽ bị ném.
Mối quan hệ tải nhanh là một trường hợp đặc biệt trong hoạt động hợp nhất. Nếu mối quan hệ tải lười biếng không được kích hoạt trên một thực thể trước khi nó bị tách ra, mối quan hệ đó sẽ bị bỏ qua khi thực thể được hợp nhất. Nếu mối quan hệ được kích hoạt trong khi được quản lý và sau đó được đặt thành null trong khi thực thể được tách ra, phiên bản được quản lý của thực thể cũng sẽ xóa mối quan hệ trong quá trình hợp nhất. "
Tất cả các thông tin trên được lấy từ "Pro JPA 2 Làm chủ API bền vững Java ™" của Mike Keith và Merrick Schnicariol. Chương 6. Phần tách ra và sáp nhập. Cuốn sách này thực sự là một cuốn sách thứ hai dành cho JPA của các tác giả. Cuốn sách mới này có nhiều thông tin mới sau đó cũ. Tôi thực sự khuyên bạn nên đọc cuốn sách này cho những người sẽ tham gia nghiêm túc với JPA. Tôi xin lỗi vì đã vô tình đăng câu trả lời đầu tiên của tôi.
Có một số khác biệt nữa giữa merge
và persist
(tôi sẽ liệt kê lại những thứ đã được đăng ở đây):
D1. merge
không làm cho thực thể được thông qua được quản lý, mà trả về một thể hiện khác được quản lý. persist
ở phía bên kia sẽ làm cho thực thể được thông qua được quản lý:
//MERGE: passedEntity remains unmanaged, but newEntity will be managed
Entity newEntity = em.merge(passedEntity);
//PERSIST: passedEntity will be managed after this
em.persist(passedEntity);
Đ2. Nếu bạn xóa một thực thể và sau đó quyết định duy trì thực thể đó trở lại, bạn có thể làm điều đó chỉ với kiên trì (), vì merge
sẽ ném một thực thể IllegalArgumentException
.
D3. Nếu bạn quyết định chăm sóc ID thủ công của mình (ví dụ: bằng cách sử dụng UUID), thì một merge
thao tác sẽ kích hoạt các SELECT
truy vấn tiếp theo để tìm kiếm các thực thể tồn tại với ID đó, trong khi persist
có thể không cần các truy vấn đó.
Đ4. Có những trường hợp khi bạn không tin tưởng mã gọi mã của mình và để đảm bảo rằng không có dữ liệu nào được cập nhật mà thay vào đó, bạn phải sử dụng persist
.
Tôi đã nhận được các trường hợp ngoại lệ lười biếng trên thực thể của mình bởi vì tôi đang cố gắng truy cập vào một bộ sưu tập được tải lười biếng trong phiên.
Những gì tôi sẽ làm là trong một yêu cầu riêng biệt, truy xuất thực thể từ phiên và sau đó thử truy cập vào một bộ sưu tập trong trang jsp của tôi có vấn đề.
Để giảm bớt điều này, tôi đã cập nhật cùng một thực thể trong bộ điều khiển của mình và chuyển nó vào jsp của tôi, mặc dù tôi tưởng tượng khi tôi lưu lại trong phiên rằng nó cũng sẽ có thể truy cập được SessionScope
và không ném LazyLoadingException
, một sửa đổi của ví dụ 2:
Sau đây đã làm việc cho tôi:
// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"
//access e from jsp and it will work dandy!!
Tôi tìm thấy lời giải thích này từ các tài liệu Hibernate khai sáng, bởi vì chúng có chứa một trường hợp sử dụng:
Việc sử dụng và ngữ nghĩa của merge () dường như gây nhầm lẫn cho người dùng mới. Thứ nhất, miễn là bạn không cố gắng sử dụng trạng thái đối tượng được tải trong một trình quản lý thực thể trong một trình quản lý thực thể mới khác, bạn không cần phải sử dụng merge () . Một số ứng dụng toàn bộ sẽ không bao giờ sử dụng phương pháp này.
Thông thường merge () được sử dụng trong kịch bản sau:
- Ứng dụng tải một đối tượng trong trình quản lý thực thể đầu tiên
- đối tượng được chuyển lên lớp trình bày
- một số sửa đổi được thực hiện cho đối tượng
- đối tượng được chuyển trở lại lớp logic nghiệp vụ
- ứng dụng vẫn duy trì các sửa đổi này bằng cách gọi merge () trong trình quản lý thực thể thứ hai
Đây là ngữ nghĩa chính xác của merge ():
- nếu có một cá thể được quản lý với cùng một mã định danh hiện được liên kết với bối cảnh bền vững, hãy sao chép trạng thái của đối tượng đã cho vào đối tượng được quản lý
- nếu không có phiên bản được quản lý hiện được liên kết với bối cảnh bền vững, hãy thử tải nó từ cơ sở dữ liệu hoặc tạo một phiên bản được quản lý mới
- cá thể được quản lý được trả về
- trường hợp cụ thể không trở nên gắn liền với bối cảnh tồn tại, nó vẫn bị tách ra và thường bị loại bỏ
Từ: http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/objectstate.html
Đi qua các câu trả lời, có một số chi tiết còn thiếu liên quan đến 'Cascade' và thế hệ id. Xem câu hỏi
Ngoài ra, điều đáng nói là bạn có thể có các Cascade
chú thích riêng để hợp nhất và tồn tại: Cascade.MERGE
và Cascade.PERSIST
sẽ được xử lý theo phương pháp được sử dụng.
Thông số kỹ thuật là bạn của bạn;)
JPA không thể chối cãi là một sự đơn giản hóa lớn trong miền ứng dụng doanh nghiệp được xây dựng trên nền tảng Java. Là một nhà phát triển đã phải đối phó với sự phức tạp của các thực thể cũ trong J2EE, tôi thấy việc đưa JPA vào các đặc tả Java EE là một bước tiến lớn. Tuy nhiên, trong khi tìm hiểu sâu hơn về các chi tiết của JPA, tôi thấy những điều không dễ dàng như vậy. Trong bài viết này, tôi đề cập đến việc so sánh các phương thức hợp nhất và liên tục của EntityManuber mà hành vi chồng chéo của họ có thể gây nhầm lẫn không chỉ với người mới. Hơn nữa, tôi đề xuất một khái quát hóa xem cả hai phương pháp là trường hợp đặc biệt của một phương pháp tổng quát hơn kết hợp.
Thực thể bền bỉ
Ngược lại với phương thức hợp nhất, phương thức kiên trì khá đơn giản và trực quan. Kịch bản phổ biến nhất về việc sử dụng phương thức kiên trì có thể được tóm tắt như sau:
"Một thể hiện mới được tạo của lớp thực thể được truyền cho phương thức kiên trì. Sau khi phương thức này trả về, thực thể được quản lý và lên kế hoạch để chèn vào cơ sở dữ liệu. Nó có thể xảy ra tại hoặc trước khi giao dịch được thực hiện hoặc khi phương thức tuôn ra được gọi. Nếu thực thể tham chiếu đến một thực thể khác thông qua mối quan hệ được đánh dấu bằng chiến lược xếp tầng PERSIST thì quy trình này cũng được áp dụng cho thực thể đó. "
Thông số kỹ thuật đi sâu vào chi tiết, tuy nhiên, việc ghi nhớ chúng là không quan trọng vì những chi tiết này chỉ bao gồm ít nhiều tình huống kỳ lạ.
Sáp nhập thực thể
So với vẫn tồn tại, việc mô tả hành vi của hợp nhất không đơn giản như vậy. Không có kịch bản chính, vì trong trường hợp vẫn tồn tại và một lập trình viên phải nhớ tất cả các kịch bản để viết mã chính xác. Dường như với tôi, các nhà thiết kế JPA muốn có một số phương thức mà mối quan tâm chính của họ sẽ là xử lý các thực thể tách rời (ngược lại với phương thức bền vững liên quan đến các thực thể mới được tạo ra chủ yếu.) Nhiệm vụ chính của phương thức hợp nhất là chuyển trạng thái từ một thực thể không được quản lý (được chuyển làm đối số) cho đối tác được quản lý của nó trong bối cảnh tồn tại. Tuy nhiên, nhiệm vụ này phân chia thành nhiều tình huống làm xấu đi tính dễ hiểu của hành vi của phương pháp tổng thể.
Thay vì lặp lại các đoạn từ đặc tả JPA, tôi đã chuẩn bị một sơ đồ dòng mô tả sơ đồ hành vi của phương thức hợp nhất:
Vì vậy, khi nào tôi nên sử dụng liên tục và khi hợp nhất?
kiên trì
hợp nhất
Kịch bản X:
Bảng: Spitter (Một), Bảng: Spittles (Nhiều) (Spittles là Chủ sở hữu của mối quan hệ với FK: spitter_id)
Kịch bản này dẫn đến việc tiết kiệm: Spitter và cả Spittles như thể được sở hữu bởi Same Spitter.
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.addSpittle(spittle3); // <--persist
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
Kịch bản Y:
Điều này sẽ cứu Spitter, sẽ cứu 2 Spittles Nhưng họ sẽ không tham chiếu cùng Spitter!
Spitter spitter=new Spitter();
Spittle spittle3=new Spittle();
spitter.setUsername("George");
spitter.setPassword("test1234");
spittle3.setSpittle("I love java 2");
spittle3.setSpitter(spitter);
dao.save(spittle3); // <--merge!!
Spittle spittle=new Spittle();
spittle.setSpittle("I love java");
spittle.setSpitter(spitter);
dao.saveSpittle(spittle); //<-- merge!!
Một quan sát khác:
merge()
sẽ chỉ quan tâm đến một id được tạo tự động (đã được thử nghiệm IDENTITY
và SEQUENCE
) khi một bản ghi với id đó đã tồn tại trong bảng của bạn. Trong trường hợp đó merge()
sẽ cố gắng cập nhật hồ sơ. Tuy nhiên, nếu một id vắng mặt hoặc không khớp với bất kỳ bản ghi hiện có nào, merge()
sẽ hoàn toàn bỏ qua nó và yêu cầu db phân bổ một bản ghi mới. Điều này đôi khi là một nguồn của rất nhiều lỗi. Không sử dụng merge()
để buộc id cho một bản ghi mới.
persist()
mặt khác sẽ không bao giờ cho phép bạn thậm chí chuyển một id cho nó. Nó sẽ thất bại ngay lập tức. Trong trường hợp của tôi, đó là:
Nguyên nhân bởi: org.hibernate.PersistentObjectException: thực thể tách rời được truyền để tồn tại
hibernate-jpa javadoc có một gợi ý:
Ném : javax.persistence.EntityExistsException - nếu thực thể đã tồn tại. (Nếu thực thể đã tồn tại, EntityExistsException có thể bị ném khi hoạt động liên tục được gọi, hoặc EntityExistsException hoặc một PersistenceException khác có thể được ném vào lúc xả hoặc cam kết.)
persist()
sẽ không phàn nàn rằng nó có ID, nó chỉ phàn nàn khi có một cái gì đó có cùng ID trong cơ sở dữ liệu.
Bạn có thể đã đến đây để được tư vấn về thời điểm sử dụng liên tục và khi nào nên sử dụng hợp nhất . Tôi nghĩ rằng nó phụ thuộc vào tình huống: khả năng bạn cần tạo một bản ghi mới và mức độ khó để lấy dữ liệu bền bỉ.
Giả sử bạn có thể sử dụng khóa / mã định danh tự nhiên.
Dữ liệu cần phải được duy trì, nhưng thỉnh thoảng một bản ghi tồn tại và một bản cập nhật được yêu cầu. Trong trường hợp này, bạn có thể thử kiên trì và nếu nó ném EntityExistsException, bạn tìm kiếm nó và kết hợp dữ liệu:
thử {entityManager.persist (entity)}
bắt (ngoại lệ EntityExistsException) {/ * truy xuất và hợp nhất * /}
Dữ liệu liên tục cần được cập nhật, nhưng thỉnh thoảng vẫn chưa có bản ghi nào cho dữ liệu. Trong trường hợp này, bạn tìm kiếm nó và tiếp tục thực hiện nếu thực thể bị thiếu:
entity = entityManager.find (key);
if (entity == null) {entityManager.persist (entity); }
khác {/ * hợp nhất * /}
Nếu bạn không có khóa / mã định danh tự nhiên, bạn sẽ khó khăn hơn để tìm hiểu xem thực thể đó có tồn tại hay không, hoặc làm thế nào để tìm kiếm nó.
Việc sáp nhập cũng có thể được xử lý theo hai cách:
kiên trì (thực thể) nên được sử dụng với các thực thể hoàn toàn mới, để thêm chúng vào DB (nếu thực thể đã tồn tại trong DB thì sẽ có EntityExistsException throw).
hợp nhất (thực thể) nên được sử dụng, để đưa thực thể trở lại bối cảnh bền vững nếu thực thể bị tách ra và được thay đổi.
Có lẽ vẫn tồn tại đang tạo ra câu lệnh INSERT sql và hợp nhất câu lệnh UPDATE sql (nhưng tôi không chắc chắn).