tl; dr
Chìa khóa để đó không phải là quá nhiều bất cứ điều gì trong mùa xuân dữ liệu REST - như bạn có thể dễ dàng có được nó để làm việc trong kịch bản của bạn - nhưng đảm bảo rằng mô hình của bạn giữ cả hai đầu của hiệp hội trong đồng bộ hóa.
Vấn đề
Vấn đề bạn thấy ở đây nảy sinh từ thực tế là mùa xuân dữ liệu REST của về cơ bản sẽ thay đổi các books
tài sản của AuthorEntity
của bạn. Chính bản thân nó không phản ánh bản cập nhật này trong thuộc tính authors
của số BookEntity
. Điều này phải được làm việc xung quanh một cách thủ công, đó không phải là một ràng buộc mà Spring Data REST tạo nên nhưng cách mà JPA hoạt động nói chung. Bạn sẽ có thể tái tạo hành vi sai lầm bằng cách đơn giản gọi thủ tục setters bằng tay và cố gắng duy trì kết quả.
Cách giải quyết vấn đề này?
Nếu loại bỏ liên kết hai chiều không phải là một lựa chọn (xem dưới đây lý do tại sao tôi khuyên bạn nên làm điều này) cách duy nhất để thực hiện công việc này là đảm bảo thay đổi liên kết được phản ánh trên cả hai mặt. Thông thường người chăm sóc này bằng cách thủ công thêm tác giả đến BookEntity
khi một cuốn sách được bổ sung:
class AuthorEntity {
void add(BookEntity book) {
this.books.add(book);
if (!book.getAuthors().contains(this)) {
book.add(this);
}
}
}
Các bổ sung nếu khoản sẽ đã được thêm vào BookEntity
bên cũng như nếu bạn muốn chắc chắn rằng thay đổi từ phía bên kia cũng được nhân giống. Các if
về cơ bản là cần thiết nếu không hai phương pháp sẽ liên tục tự gọi mình.
REST dữ liệu mùa xuân, theo mặc định sử dụng truy cập trường để thực tế không có phương pháp nào bạn có thể đặt logic này vào. Một tùy chọn sẽ là chuyển sang quyền truy cập thuộc tính và đặt logic vào các bộ định tuyến. Một tùy chọn khác là sử dụng phương thức được chú thích bằng @PreUpdate
/@PrePersist
lặp lại qua các thực thể và đảm bảo rằng các sửa đổi được phản ánh trên cả hai mặt.
Xóa nguyên nhân gốc của sự cố
Như bạn có thể thấy, điều này thêm khá nhiều phức tạp cho mô hình miền.Như tôi đã nói đùa trên Twitter ngày hôm qua:
# 1 quy tắc của các hiệp hội hai chiều: không sử dụng chúng ... :)
Nó thường đơn giản hoá vấn đề này nếu bạn cố gắng không sử dụng hai chiều mối quan hệ bất cứ khi nào có thể và thay vào đó rơi trở lại một kho lưu trữ để có được tất cả các thực thể tạo nên mặt sau của hiệp hội.
Một chẩn đoán tốt để xác định bên nào cần cắt giảm là suy nghĩ về khía cạnh nào của liên kết thực sự cốt lõi và quan trọng đối với miền bạn đang lập mô hình. Trong trường hợp của bạn, tôi cho rằng nó là hoàn toàn tốt đẹp cho một tác giả để tồn tại mà không có cuốn sách được viết bởi cô ấy. Mặt khác, một cuốn sách không có tác giả không có ý nghĩa gì cả. Vì vậy, tôi muốn giữ authors
tài sản trong BookEntity
nhưng giới thiệu các phương pháp sau đây trên BookRepository
:
interface BookRepository extends Repository<Book, Long> {
List<Book> findByAuthor(Author author);
}
Vâng, đó là yêu cầu tất cả các khách hàng mà trước đây chỉ có thể gọi author.getBooks()
đến nay làm việc với một kho lưu trữ. Nhưng về mặt tích cực, bạn đã loại bỏ tất cả các cruft từ các đối tượng miền của bạn và tạo ra một hướng phụ thuộc rõ ràng từ cuốn sách cho tác giả trên đường đi. Sách phụ thuộc vào tác giả nhưng không phụ thuộc vào cách khác.
Các liên kết hai chiều phải được duy trì theo cách thủ công trong mô hình đối tượng thường được thực hiện bên trong bộ cài đặt. Spring Data REST sử dụng truy cập trường theo mặc định. Điều đó có nghĩa là sự thay đổi trong các hiệp hội không được phản ánh ở phía bên kia của hiệp hội theo định nghĩa. Bạn đã thử, kích hoạt đồng bộ hóa trong phương thức '@ PrePersist' /' @ PreUpdate' chưa? Hoặc chuyển sang quyền truy cập thuộc tính? –
Tôi cũng sẽ bỏ phiếu để giải quyết hiệp hội hai chiều. Một 'Tác giả' có thể tồn tại mà không có 'Sách'. 'Sách' cho 'Tác giả' có thể được lấy ra bằng cách sử dụng một phương thức kho lưu trữ' Đặt BookRepository.findByAuthor (Tác giả tác giả) '. Điều này đơn giản hóa mô hình khá một chút vì bạn không phải tự duy trì các tham chiếu. –
Tôi có thể thấy một giao diện thư viện nơi bạn sẽ cần phải tìm một tác giả, sau đó xem sách của nó. Điều này sẽ không được hỗ trợ nếu không có các hiệp hội hai hướng. Không phải là một fan hâm mộ của việc quản lý các hiệp hội thực thể nếu nó không phải là ý định của DATA REST. Cảm ơn bạn đã nhập và lọc sách của tác giả dường như là cách tiếp cận tốt nhất. Không giữ mọi thứ một chiều bất cứ khi nào có thể. :) – keaplogik