2010-01-07 28 views
85

Câu hỏi nằm 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 nào và tại sao thực thể JPA nên triển khai giao diện Serializable?

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 Serializable.

Nhưng khi mô hình miền trở nên phức tạp hơn, tôi nhận được RuntimeException cho biết rằng một trong các thực thể của tôi đã không triển khai Serializable.

Tôi sử dụng Hibernate làm triển khai JPA.

Tôi tự hỏi:

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

Trả lời

33

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

34

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

Chỉ vì lợi ích của sự kiên trì, Serializable là không cần thiết, ít nhất là với Hibernate. Nhưng thực hành tốt nhất là làm cho chúng Serializable.

+2

Tôi không biết, có thể các thực thể của tôi đang được chuyển ngầm ở đâu đó. Tôi sử dụng hibernate + spring + jsf và Tomcat. Việc chuyển giao chuỗi này có thể diễn ra ở đâu? – Roman

4

Các lớp học phải triển khai có thể 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à một 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ể, mà đòi hỏi họ phải được serializable.

92

Theo JPA Spec:

Nếu một ví dụ thực thể là phải được thông qua bởi giá trị như một đối tượng tách ra (ví dụ, thông qua một giao diện từ xa), các lớp thực thể phải thực hiện các giao diện Serializable.

"JSR 220: Doanh nghiệp JavaBeansTM, Phiên bản 3.0 Java Persistence API Phiên bản 3.0, Final phát hành ngày 02 tháng 5 năm 2006"

+11

(+1) nhìn vào thông số kỹ thuật luôn luôn hiệu quả – Bozho

+9

Tôi không thấy lý do tại sao điều này có rất nhiều upvotes. OP nói rằng nó không được yêu cầu khi mô hình đơn giản hơn. Gửi các đối tượng từ xa thông qua serialization Java sẽ luôn luôn yêu cầu các đối tượng được Serializable, 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

+0

Tôi không hoàn toàn chắc chắn về hibernate, 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 bản sao của một thực thể (đối tượng). 'Serializable' có thể hữu ích với điều đó, và trong bối cảnh kiên trì nhất quán hơn' Cloneable' chẳng hạn. – JimmyB

4

Tôi tin rằng vấn đề của bạn có liên quan đến việc có một lĩnh vực của một loại phức tạp (class) mà không được chú thích. Trong trường hợp này việc xử lý mặc định sẽ lưu trữ các đối tượng trong đó là hình thức tuần tự trong cơ sở dữ liệu (mà có lẽ không phải là những gì bạn có nghĩa là để 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 phía trên CustomerData sẽ được lưu trong một mảng mảng byte trong cơ sở dữ liệu ở dạng tuần tự của nó.

8

Để bổ sung cho câu trả lời hay của Conor, người đã đề cập đến các đặc điểm 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 giao diện từ xa. Trong trường hợp này, bạn cần phải làm cho bean thực thể của bạn có thể tuần tự hóa được vì chúng được tổng hợp trong EJB từ xa và được xây dựng để có dây thông qua mạng.

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: Beans that use session, application, or conversation scope must be serializable, but beans that use request scope do not have to be serializable. Do đó, đối tượng thực thể JPA cơ bản -if any- sẽ tuân theo cùng ngữ nghĩa đó.

1

Theo hibernate docs, trong khi sử dụng @JoinColumn chú thích:

Nó đã thêm một thông 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 referencedColumnName cho cột khóa không chính, lớp được liên kết phải là Serializable.

0

Đây cũng là lỗi được ném khi bạn chuyển ID không chính xác làm thông số thứ hai cho một cái gì đó như em.find() (nghĩa là tự chuyển đối tượng chứ không phải ID của nó). Tôi đã không tìm thấy nó nhưng cần thiết để thực sự khai báo các thực thể JPA serializable - nó không thực sự cần thiết trừ khi bạn đang sử dụng referencedColumnName như được mô tả bởi aman.

0

nhấn từ xa bằng cách sử dụng người đưa thư 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 fasterxml.So, tốt hơn là sử dụng bộ nối tiếp.

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