2011-09-15 9 views
9

Tôi hiện đang lăn ORM nhỏ của riêng mình và thấy mình phải đối mặt với nhiệm vụ tạo bản đồ chuẩn hóa để ngăn việc tải cùng một thực thể từ cơ sở dữ liệu nhiều lần.Làm cách nào để triển khai ánh xạ chuẩn hóa trong Java?

Cách tiếp cận hiện tại của tôi là sử dụng HashMap<Object, WeakReference<Object>>. Khóa là khóa chính của thực thể cơ sở dữ liệu được ánh xạ (một ArrayList<Object> nếu đó là khóa tổng hợp) và các giá trị là WeakReference<Object>.

Vấn đề chính của tôi là làm thế nào để làm sạch bản đồ? Khi một đối tượng không được sử dụng nữa, tham chiếu yếu trong bản đồ sẽ đi null và tôi sẽ chỉ khám phá điều này trong lần tra cứu tiếp theo (hoặc không bao giờ, nếu tôi không nhìn lại đối tượng). Tôi có thể làm cho các tài liệu tham khảo yếu đăng ký với một ReferenceQueue khi họ nhận được xóa, và sau đó kiểm tra hàng đợi đó mỗi khi tôi nhìn cái gì đó lên. Các tham chiếu đã xóa sẽ không cho tôi bất kỳ gợi ý nào về đối tượng nào đã bị xóa, vì vậy tôi đoán tôi sẽ phải phân lớp WeakReference để lưu khóa trong bản đồ, vì vậy tôi có thể xóa nó sau khi tham chiếu bị xóa.

Đây có phải là cách để đi hay không có cách nào đơn giản hơn để triển khai tính năng này?

Trả lời

13

Tôi khuyên bạn nên sử dụng Guava's MapMaker hoặc CacheBuilder trong r10.

Chúng cho phép tự động * trục xuất theo thời gian và kích thước, cũng như hỗ trợ khóa hoặc giá trị yếu. (Các CacheBuilder hứa hẹn sắp tới được đặc biệt thiết kế riêng cho loại trường hợp sử dụng.)

Vì vậy, bạn có thể khởi tạo bản đồ của bạn:

ConcurrentMap<Key, Object> cache = new MapMaker() 
     .weakValues() 
     .makeMap(); 

Và lợi ích ngay lập tức sẽ được rằng khi một giá trị được thu gom rác thải, các toàn bộ mục nhập sẽ bị xóa. Hơn nữa, bạn có thể sử dụng bản đồ tính toán:

ConcurrentMap<Key, Object> cache = new MapMaker() 
     .weakValues() 
     .makeComputingMap(loadFunction); 

nơi loadFunction là một Function<Key, Object> rằng tải một đối tượng từ cơ sở dữ liệu. Ưu điểm của điều này là bản đồ sẽ xử lý các yêu cầu đồng thời cho một đối tượng cụ thể, đảm bảo truy vấn chỉ được gọi một lần. Ngoài ra, mã yêu cầu chỉ cần gọi get() và luôn có thể mong đợi đối tượng quay lại, cho dù từ bộ nhớ cache hoặc cơ sở dữ liệu.

Những ví dụ này đang sử dụng MapMaker - Tôi chưa có niềm vui khi được chơi với CacheBuilder.

Xem câu hỏi của tôi my ideal cache using guava để biết thêm ví dụ. Bài đăng đó thảo luận về cách kết hợp việc loại bỏ dựa trên thời gian với sự chuẩn hóa.

+2

Tôi đã do dự trước khi thêm thư viện này, nhưng bây giờ tôi đã làm, tôi tự hỏi tại sao tôi không làm điều đó sớm hơn. Cảm ơn câu trả lời tuyệt vời này! –