Khi nào và tại sao các thực thể JPA nên thực hiện giao diện Nối tiếp?


151

Câu hỏi là trong tiêu đề. Dưới đây tôi chỉ mô tả một số suy nghĩ và phát hiện của tôi.

Khi tôi có mô hình miền rất đơn giản (3 bảng không có bất kỳ mối quan hệ nào), tất cả các thực thể của tôi KHÔNG thực hiện Nối tiếp.

Nhưng khi mô hình miền trở nên phức tạp hơn, tôi đã có RuntimeException nói rằng một trong những thực thể của tôi đã không triển khai Nối tiếp.

Tôi sử dụng Hibernate như một triển khai JPA.

Tôi tự hỏi:

  1. Có phải là yêu cầu / hành vi cụ thể của nhà cung cấp?
  2. Điều gì xảy ra với các thực thể tuần tự hóa của tôi? Chúng nên được tuần tự hóa để lưu trữ hoặc chuyển giao?
  3. Tại thời điểm nào nó trở nên cần thiết để làm cho thực thể của tôi tuần tự hóa?

Câu trả lời:


59

Điều này thường xảy ra nếu bạn trộn HQL và truy vấn SQL gốc. Trong HQL, Hibernate ánh xạ các loại bạn truyền vào bất cứ điều gì DB hiểu. Khi bạn chạy SQL gốc, thì bạn phải tự thực hiện ánh xạ. Nếu bạn không, thì ánh xạ mặc định là tuần tự hóa tham số và gửi nó đến cơ sở dữ liệu (với hy vọng rằng nó hiểu nó).


Điều này không giải thích tại sao chỉ "có lẽ như thế nào" Xem câu trả lời dưới đây từ Bozho
chrips

là thực thể có nghĩa là sẽ được lưu trong DB mà không thực hiện giao diện tuần tự hóa?
Hanumantha_3048092

@ Hanumantha_3048092 Có. Ánh xạ thực thể và Serializablelà hai khái niệm khác nhau.
Aaron Digulla

@AaronDigulla Bạn có thể vui lòng giải thích nó bằng một ví dụ hoặc mã giả.
sdindiver

110

Theo Thông số kỹ thuật của JPA:

Nếu một thực thể được truyền theo giá trị dưới dạng một đối tượng tách rời (ví dụ, thông qua một giao diện từ xa), lớp thực thể phải thực hiện giao diện Nối tiếp.

"JSR 220: JavaBeansTM doanh nghiệp, API phiên bản 3.0 bền vững Java phiên bản 3.0, Bản phát hành cuối cùng ngày 2 tháng 5 năm 2006"


14
(+1) nhìn vào thông số kỹ thuật luôn có kết quả
Bozho

20
Tôi không thấy lý do tại sao điều này có rất nhiều upvote. OP nói rằng nó không cần thiết khi mô hình đơn giản hơn. Gửi các đối tượng từ xa thông qua tuần tự hóa Java LUÔN LUÔN yêu cầu các đối tượng phải được Tuần tự hóa, bất kể độ phức tạp của nó. Rõ ràng đây không phải là trường hợp sử dụng của OP.
Robin

Tôi không chắc chắn về chế độ ngủ đông, nhưng với các nhà cung cấp JPA khác, có các hoạt động yêu cầu nhà cung cấp tạo một bản sao của một thực thể (đối tượng). Serializablecó thể hữu ích với điều đó, và trong bối cảnh kiên trì phù hợp hơn so Cloneablevới ví dụ.
JimmyB

Câu trả lời này chỉ là một bãi chứa thông tin và hoàn toàn không giúp ai đó hiểu lý do tại sao.
chrips

59

Bạn cần các thực thể của mình là Serializablenếu bạn cần chuyển chúng qua mạng (tuần tự hóa chúng sang một số đại diện khác), lưu trữ chúng trong phiên http (lần lượt được tuần tự hóa vào đĩa cứng bởi thùng chứa servlet), v.v.

Chỉ vì sự kiên trì, Serializablekhông cần thiết, ít nhất là với Hibernate. Nhưng nó là một thực hành tốt nhất để làm cho họ Serializable.


2
Tôi không biết, có thể các thực thể của tôi đang được chuyển hoàn toàn ở đâu đó. Tôi sử dụng hibernate + spring + jsf và Tomcat. Trường hợp trong chuỗi chuyển nhượng này có thể diễn ra?
La Mã

@Roman ví dụ người dùng hiện tại (có thể là một thực thể) và tất cả các thực thể liên quan của nó có thể kết thúc trong phiên, như Bozho nói có thể được tuần tự hóa vào đĩa bởi bộ chứa servlet.
OrangeDog

Đây là câu trả lời tốt nhất "tại sao và khi nào"! Thông thoáng! Cảm ơn bạn
chrips

13

Theo các tài liệu ngủ đông , trong khi sử dụng chú thích @JoinColumn:

Nó có thêm một tham số được đặt tên referencedColumnName. Tham số này khai báo cột trong thực thể được nhắm mục tiêu sẽ được sử dụng để tham gia. Lưu ý rằng khi sử dụng referencedColumnNamecho một cột khóa chính, lớp liên quan phải là Serializable.


8

Để bổ sung cho câu trả lời hay của Conor, người đã tham khảo các thông số kỹ thuật của JSR-317. Thông thường, các dự án EAR bao gồm một mô-đun EJB với các EJB được hiển thị thông qua một giao diện từ xa. Trong trường hợp này, bạn cần làm cho các bean thực thể của mình được tuần tự hóa khi chúng được tổng hợp trong EJB từ xa và được xây dựng để được nối qua mạng.

Một dự án chiến tranh JEE6 không có CDI: có thể chứa EJB lite được hỗ trợ bởi các thực thể JPA không tuần tự hóa.

Dự án chiến tranh JEE6 với CDI: Đậu sử dụng phạm vi phiên, ứng dụng hoặc phạm vi hội thoại phải được tuần tự hóa, nhưng các hạt sử dụng phạm vi yêu cầu không phải được tuần tự hóa. Do đó, các thực thể JPA cơ bản - nếu có - sẽ tuân theo cùng một ngữ nghĩa.


7

Nếu chúng ta chỉ nói về sự kiên trì, Serializablethì không cần thiết Nhưng tốt nhất là tạo ra các thực thể Serializable.

Nếu chúng ta đang phơi bày domain/ entitiescác đối tượng tiếp xúc trực tiếp với lớp trình bày, thay vì sử dụng DTO, Trong trường hợp đó chúng ta cần thực hiện Serializable. Các đối tượng miền này có thể được lưu trữ HTTPSessioncho mục đích lưu trữ / tối ưu hóa. Một phiên http có thể được nối tiếp hoặc phân cụm. Và nó cũng được yêu cầu để chuyển dữ liệu giữa các JVMlần.

Khi chúng ta sử dụng DTOđể tách lớp lớp bảo trì và lớp dịch vụ, việc đánh dấu các đối tượng miền Serializablesẽ phản tác dụng và sẽ vi phạm phạm lỗi encapsulation. Sau đó, nó trở thành một mô hình chống.

Định danh tổng hợp

Lớp khóa chính phải được tuần tự hóa.

Mô hình POJO

Nếu một thực thể được sử dụng từ xa như một đối tượng tách rời, lớp thực thể phải thực hiện Serializablegiao diện.

Bộ nhớ cache
Thêm vào đó, nếu bạn đang thực hiện một clusteredmức độ thứ hai cachesau đó tổ chức của bạn phải serializable. Mã định danh phải là Serializablevì đó là một yêu cầu của JPA vì identifiercó thể được sử dụng làm khóa cho mục nhập bộ đệm cấp hai.

Và khi chúng tôi tuần tự hóa các thực thể, hãy đảm bảo cung cấp rõ ràng serialVersionUIDvới công cụ sửa đổi truy cập riêng. Bởi vì nếu một serializablelớp không khai báo rõ ràng a serialVersionUID, thì thời gian chạy tuần tự hóa sẽ tính toán một serialVersionUIDgiá trị mặc định cho lớp đó dựa trên các khía cạnh khác nhau của lớp, như được mô tả trong Đặc tả tuần tự hóa đối tượng Java (TM). serialVersionUIDTính toán mặc định rất nhạy cảm với các chi tiết lớp có thể thay đổi tùy thuộc vào việc triển khai trình biên dịch và do đó có thể dẫn đến bất ngờ InvalidClassExceptionstrong quá trình khử lưu huỳnh.


6

Tôi tin rằng vấn đề của bạn liên quan đến việc có một trường thuộc loại (lớp) phức tạp không được chú thích. Trong những trường hợp như vậy, việc xử lý mặc định sẽ lưu trữ đối tượng ở dạng tuần tự của nó trong cơ sở dữ liệu (có lẽ không phải là điều bạn muốn làm) Ví dụ:

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

Trong trường hợp trên, CustomerData sẽ được lưu trong trường mảng byte trong cơ sở dữ liệu ở dạng tuần tự.


5

Đặc điểm kỹ thuật của JPA

Theo đặc tả của JPA, một thực thể chỉ nên thực hiện Serializablenếu nó cần được truyền từ JVM này sang JVM khác hoặc nếu thực thể đó được sử dụng bởi Bean phiên phiên bản cần được thụ động bởi bộ chứa EJB.

Nếu một thực thể được truyền theo giá trị dưới dạng một đối tượng tách rời (ví dụ, thông qua một giao diện từ xa), lớp thực thể phải thực hiện Serializablegiao diện.

Ngủ đông

Hibernate chỉ yêu cầu các thuộc tính thực thể Serializable, nhưng không phải là chính thực thể.

Tuy nhiên, khi triển khai đặc tả JPA, tất cả các yêu cầu của JPA liên quan đến Serializablecác thực thể cũng áp dụng cho Hibernate.

Mèo con

Theo tài liệu Tomcat , các HttpSessionthuộc tính cũng cần phải là Serializable:

Bất cứ khi nào Apache Tomcat bị tắt bình thường và được khởi động lại hoặc khi kích hoạt tải lại ứng dụng, việc triển khai Trình quản lý tiêu chuẩn sẽ cố gắng tuần tự hóa tất cả các phiên hiện hoạt động thành một tệp đĩa được đặt thông qua thuộc tính tên đường dẫn. Tất cả các phiên đã lưu như vậy sau đó sẽ được giải nén và kích hoạt (giả sử chúng chưa hết hạn trong thời gian trung bình) khi quá trình tải lại ứng dụng hoàn tất.

Để khôi phục thành công trạng thái của các thuộc tính phiên, tất cả các thuộc tính như vậy PHẢI triển khai giao diện java.io.Serializable.

Vì vậy, nếu thực thể được lưu trữ trong HttpSession, nó sẽ thực hiện Serializable.


4

Các lớp phải thực hiện tuần tự hóa nếu bạn muốn tuần tự hóa chúng. Điều này không liên quan trực tiếp đến JPA và đặc tả JPA không yêu cầu các thực thể được tuần tự hóa. Nếu Hibernate thực sự phàn nàn về điều này, tôi cho rằng đó là lỗi Hibernate, nhưng tôi cho rằng bạn trực tiếp hoặc gián tiếp đang làm một cái gì đó khác với các thực thể, đòi hỏi chúng phải được tuần tự hóa.


3

Vui lòng tham khảo http://www.adam-bien.com/cont/abien/entry/do_jpa_entities_have_to nó nói, Việc triển khai java.io.Serializable chỉ đơn giản là cần thiết để chuyển dữ liệu qua IIOP hoặc JRMP (RMI) giữa các phiên bản JVM. Trong trường hợp ứng dụng web thuần túy, các đối tượng miền đôi khi được lưu trữ trong HTTPSession cho mục đích lưu trữ / tối ưu hóa. Một phiên http có thể được tuần tự hóa (thụ động) hoặc phân cụm. Trong cả hai trường hợp, tất cả các nội dung phải được nối tiếp.


1

nhấn từ xa bằng cách sử dụng postman hoặc ajax hoặc js góc, v.v. ....., có thể gây ra chu kỳ lặp lại với ngoại lệ StackOverflow với Jackson quickxml. Vì vậy, tốt hơn là sử dụng serializer.


1
  1. Tại thời điểm nào nó trở nên cần thiết để làm cho thực thể của tôi tuần tự hóa?

Việc triển khai ehcache với @Cacheablekho lưu trữ dưới dạng bộ đệm cấp hai (tức là sử dụng chú thích trên thực thể hoặc phương thức lưu trữ / dịch vụ) yêu cầu Nối tiếp, nếu không bộ đệm sẽ thất bại ( NotSerializableException) để ghi thực thể vào bộ đệm của đĩa.


0

Đây cũng là lỗi được đưa ra khi bạn chuyển ID được nhập sai thành thông số thứ hai cho một cái gì đó như em.find () (tức là truyền chính thực thể thay vì ID của nó). Tôi chưa thấy cần phải thực sự khai báo các thực thể JPA tuần tự hóa - nó không thực sự cần thiết trừ khi bạn đang sử dụng tham chiếuColumnName như được mô tả bởi aman.


0

khi các thực thể JPA được sử dụng làm tham số hoặc trả về giá trị bởi các hoạt động EJB từ xa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.