2011-01-13 31 views
6

Một ứng dụng tôi đang làm việc trên sử dụng Hibernate dành riêng để tìm nạp một loạt các đối tượng liên tục từ cơ sở dữ liệu đến bộ nhớ. Ứng dụng này là làm mới ảnh chụp nhanh trong bộ nhớ này từ cơ sở dữ liệu mọi lúc và sau đó, và đó sẽ là giao tiếp duy nhất với cơ sở dữ liệu.Làm cách nào để tải một tập hợp bản đồ Hibernate thành một bộ không thể sửa đổi được?

Các đối tượng trong bộ nhớ sau đó được sử dụng cho một loạt các phép tính. Các phép tính không được sửa đổi các đối tượng này. Ngoại trừ một số lớp học một nơi nào đó vô tình đã làm, và tôi đã phải dành một ngày săn lùng các lỗi. Bây giờ tôi tự hỏi cách tốt nhất để làm cho toàn bộ cây đối tượng bất biến là gì.

Giả sử hệ thống phân cấp lớp trông như thế này:

public class Building { // persistent entity 
    private String name; // hibernate-mapped property 
    private Set<Person> inhabitants; // hibernate-mapped collection 

    // getters 
} 

public class Person { // persistent entity 
    private String name; // hibernate-mapped property 

    // getters 
} 

tôi đã ngăn chặn khách hàng truy cập vào cơ sở dữ liệu theo:

  • háo hức lấy tất cả các đơn vị và các bộ sưu tập
  • đánh dấu tất cả các đơn vị và các bộ sưu tập với mutable=false trong ánh xạ Hibernate
  • không cung cấp bất kỳ phiên bản nào của phiên Hibernate hoặc trạng thái thay đổi g dao phương pháp.

Bây giờ lỗi tôi muốn ngăn chặn là, ai đó vô tình đi building.getInhabitants().clear();. Tôi có thể nghĩ đến các tùy chọn này:

  1. Getter gói: Hãy getInhabitants đầu tiên quấn inhabitants trong một cuộc gọi Collections.unmodifiableSet(), sau đó trả lại.

    • Ưu điểm: công việc nhỏ nhất, thêm ít nhất đang
    • Nhược điểm: Cảm thấy hacky
  2. lớp Wrapper: Đổi tên Building-MutableBuilding, Person-MutablePerson, và cung cấp các lớp học bất biến BuildingPerson. Vì ứng dụng của tôi có một điểm chụp rõ ràng, tôi có thể lấy các bản ghi như các đối tượng có thể thay đổi (như tôi làm bây giờ), tạo các bản sao không thay đổi sâu sắc và trình bày cây đối tượng đó cho các máy khách.

    • Ưu điểm: Thẳng java, không có phép thuật Hibernate. Tôi có thể sử dụng từ khóa yêu thích của mình: final
    • Nhược điểm: Mã khác để viết và duy trì. Ngoài ra, Hibernate sẽ giữ các trường hợp có thể thay đổi trong bộ nhớ?
  3. Hibernate lập bản đồ ma thuật: Sử dụng rằng một từ khóa ma thuật để hướng dẫn Hibernate để bọc các bộ sưu tập nó đặt trên các đối tượng thực thể của tôi trong Collections.unmodifiableSet() hoặc tương đương.(Lưu ý: Tôi sử dụng một tập tin mapping xml)

    • Ưu điểm: Elegant, không có mã thêm
    • Nhược điểm: từ khóa này có thể không tồn tại
  4. Hibernate mở rộng: Sử dụng rằng một phần mở rộng Hibernate điểm để viết instantiator đối tượng của riêng tôi, và trong đó quấn các thiết lập trong Collections.unmodifiableSet() trước khi trả lại nó.

    • Ưu điểm: Nhiều thanh lịch hơn hack getters tôi
    • Nhược điểm: điểm mở rộng này có thể không tồn tại

Ngay bây giờ tôi đang nghiêng về phía # 2, chủ yếu là bởi vì tôi không biết nếu 3 và 4 là có thể.

Cách tốt nhất là gì?

Trả lời

6

Tùy chọn 1, chắc chắn. Nó không phải là "hacky", và đó là lý do tại sao bạn trừu tượng truy cập tài sản vào các phương thức, ở nơi đầu tiên :-) Chỉ cần lưu ý rằng bạn nên sử dụng "truy cập trường" với Hibernate, thay vì "method", để bạn không rủi ro cung cấp một bộ sưu tập unmodifiable để Hibernate.

Thật không may, Hibernate không cung cấp cách đặt các bộ sưu tập không thể sửa đổi, nhưng tôi nghĩ bạn có thể thực hiện một trình nghe sự kiện @PostLoad để sửa đổi tất cả các bộ sưu tập khi đối tượng được tải.

+0

+1 để nhắc tôi lý do tại sao chúng tôi viết getters và setters :-) – KarlP

+0

Điều này dường như là giải pháp tốt nhất. Tôi sẽ phải đi đến các điều khoản với thực tế là các lớp học có thể thay đổi đôi khi được rồi! :) – oksayt

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