2010-03-16 25 views
5

Tôi rất mới với Java nhưng tôi đã phát triển một thói quen để sử dụng cuối cùng bất cứ nơi nào có thể tuyên bố bất biến mà tôi nghĩ là một điều tốt. (Xem xét f #)Nhà cung cấp kiên trì cho Java hỗ trợ các trường cuối cùng

Tôi đã đọc rằng JPA không hỗ trợ các trường cuối cùng. Hibernate, TopLink? Tôi không chắc chắn về những điều này nhưng tôi thích JPA cho bây giờ.

Điều đó thậm chí có thể về mặt lý thuyết - hãy nói qua sự phản chiếu - để sửa đổi các trường cuối cùng sau khi tạo? Dự đoán của tôi sẽ là ... NO :)

Điều chắc chắn có thể cho giải pháp kiên trì là hỗ trợ các nhà thầu với các tham số. Ít nhất tôi không thấy lý do nào khiến điều này là không thể. Lập bản đồ sẽ là một chút khôn lanh tôi đoán. Đây là giải pháp thay thế.

Đề xuất?

EDIT: Tôi không quen với định nghĩa chính xác cho bất biến nên tôi đã sử dụng nó trong bài đăng này một cách trực quan. Khai báo Tính bất biến ở đây có nghĩa là tuyên bố rằng một trường không thể thay đổi được. Xin lỗi vì sự hiểu lầm.

Trả lời

6

Bất biến đối tượng (chú ý sự khác biệt giữa đối tượng bất biến và khai báo trường cuối cùng - đối tượng CHỈ là không thay đổi nếu TẤT CẢ trường cuối cùng, do đó trạng thái của đối tượng không thể thay đổi sau khi tạo) là một chủ đề rất nhạy cảm. Tôi thích chúng, và hibernate hỗ trợ chúng thông qua @Immutable.

Không biết về trạng thái của nó trong JPA 2, nhưng để trả lời câu hỏi về các trường cuối cùng: bạn CÓ THỂ thay đổi giá trị của chúng bằng cách sử dụng sự phản chiếu - nhưng phản ánh bị hạn chế nghiêm trọng trong môi trường Java EE.

Để khai sáng vấn đề chính: nếu POJO của bạn là bất biến, thì làm thế nào một giải pháp liên tục sẽ tái tạo các đối tượng? Giả sử bạn có hai trường int cuối cùng và một hàm khởi tạo để khởi tạo chúng. Lớp persistence không thể có bất kỳ thông tin nào về thứ tự của chúng, hoặc tên của chúng (như các tên trường và tham số được xóa trong quá trình biên dịch).

Koshuke đã đăng một blog về điều này (liên quan đến JAXB hỗ trợ đậu không thay đổi), nhưng không thể tìm thấy ngay bây giờ.

-1

Đây thực sự là một ý tưởng lạ.

Bằng cách tạo trường final, bạn cho trình biên dịch biết họ sẽ không bao giờ thay đổi sau khi tạo đối tượng. Kết quả là, nó là một giả định hợp lý để không tồn tại chúng, vì chúng sẽ không bao giờ thay đổi. Vâng, bằng cách viết này, tôi giả sử bạn có văn hóa java, nhưng câu hỏi bạn hỏi chính xác nói ngược lại.

Trong Java, các truy vấn dai dẳng "luôn" được giả định là POJO (nói cách khác, Java Beans). Một Java Bean phải có (được coi như là) một hàm tạo rỗng cho phép các khuôn khổ bền vững và cứ như vậy để xây dựng nó bằng cách sử dụng hàm tạo rỗng của nó, bằng cách gián tiếp gọi nó thông qua Class.newInstance() /.

Có những trường không sử dụng các hàm tạo rỗng (như vùng chứa IoC - Guice, Spring và Tapestry IoC), nhưng nằm ngoài phạm vi của Java Beans, được coi là đối tượng dữ liệu.

+0

Điều gì về cơ sở dữ liệu chỉ đọc? BTW Tôi chỉ khám phá những khả năng. – naeron84

+0

Các trường hợp sử dụng khác: nhiều thực thể cho một bảng. Hoặc tạo các thực thể đó thông qua một phương thức nhà máy. – naeron84

1

Điều này có thể không chính xác những gì bạn đang phấn đấu, nhưng nguyên tắc bất biến có thể dễ dàng được hỗ trợ bởi các trường riêng tư không phải cuối cùng chỉ có một getter. Trình biên dịch trong thực tế nhận ra điều này và tạo ra mã mà là khá nhiều giống hệt với những gì bạn muốn có được với các lĩnh vực tuyên bố là cuối cùng.

Điều này sẽ yêu cầu bạn phải tận tâm và không thay đổi trường của bạn từ bên trong lớp chứa (trong khi final sẽ thực thi điều đó), nhưng tôi nghĩ đây không phải là một mức giá lớn để trả cho sự linh hoạt bạn có được.

0

Không thể sửa đổi các trường cuối cùng sau khi tạo theo thiết kế. Làm theo cách khác là một ý tưởng rất tồi, bởi vì ai đó có thể dựa vào hành vi tiêu chuẩn.

Nói chung, các khuôn khổ bền vững đối phó với các cấu trúc phân cấp của các đối tượng "bình thường". Bạn có các đối tượng, chỉ có thể được tạo và xóa, không được sửa đổi. Điều đó rất kỳ quặc, bởi vì khi bạn tạo ra một thực thể, bạn tạo ra một số loại ID cho nó. Thông qua ID này, bạn kết nối thực thể với người khác. Khi bạn loại bỏ thực thể cũ và tạo một thực thể khác, bạn (nói chung) có được một thực thể với một ID khác. Vì vậy, tất cả các kết nối (khóa ngoại) đều bị hỏng. Đó là hành vi mục tiêu?

+0

Bạn thực hiện một số điểm hợp lệ; +1. –

1

Câu hỏi hay. Trên thực tế nó là một ý tưởng tốt để tuyên bố các lĩnh vực như là cuối cùng nếu họ không thay đổi (bạn nhận được sau đó khởi tạo đảm bảo từ JMM).

Các JPA Spec là rõ ràng liên quan đến lĩnh vực thức:

lớp Thực thể không phải là chính thức. Không có phương pháp hoặc biến đối tượng cố định của lớp thực thể có thể là cuối cùng.

Hoever, không phải tất cả triển khai theo quy tắc này và xử lý các lĩnh vực thức:

  • OpenJPA không hỗ trợ các lĩnh vực cuối cùng, tức là họ đang được coi là thoáng qua. Khi tải các trường cuối cùng của thực thể như vậy được khởi tạo với các giá trị như được xác định trong hàm tạo parameterless.

  • Việc triển khai Hibernate tuy nhiên hỗ trợ các trường cuối cùng. Khi xây dựng các lĩnh vực cuối cùng đã được khởi tạo trong constructor parameterless được thay thế bằng các giá trị được lưu trữ trong cơ sở dữ liệu.

Vì vậy, để trả lời câu hỏi của bạn: Vâng, có những nhà cung cấp kiên trì JPA có hỗ trợ các lĩnh vực cuối cùng, tuy nhiên tôi khuyên bạn nên không sử dụng các lĩnh vực cuối cùng trong lớp thực thể của bạn như là hành vi không được định nghĩa (và thực sự khác với nhà cung cấp đến nhà cung cấp). Hơn nữa, tôi nghĩ rằng một ý tưởng tồi là một nhà cung cấp JPA thay đổi các trường cuối cùng sau khi xây dựng vì bảo đảm khả năng hiển thị có thể bị vi phạm theo cách này.

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