2011-01-27 33 views
5
cấu trúc

Object là nhưLấy một cấu trúc đồ thị trong Hibernate

  • Invoice này
    • khách hàng
    • ngày
    • Số
    • có nhiều ProductLines (sản phẩm, Số lượng, Giá)
    • có nhiều ServiceLines (Dịch vụ, Số lượng, Giá)
    • có nhiều PaymentOptions (PaymentType (Kiểm tra, Tiếp nhận, vv.), Date, Sum)

Nếu tôi cần phải lấy một danh sách các hoá đơn có thời hạn với Hibernate là rất dễ dàng để làm với lười biếng tải mà không cần viết bất kỳ mã nào chỉ cần gọi ... NHƯNG có nhược điểm của quá nhiều cuộc gọi DB, vì vậy trong môi trường đa người dùng, giải pháp này không ổn.

Với JDBC đơn giản, tôi đã giải quyết vấn đề này bằng cách sử dụng 3 truy vấn: 3 tham gia giữa Invoice và ProductLines, Invoice and ServiceLines và Invoice and Payment Options. Sau đó tôi xây dựng đối tượng trong bộ nhớ. Tương tự có thể được thực hiện với Hibernate Tôi biết NHƯNG câu hỏi của tôi là không có thứ như đồ thị tải hoặc vì vậy tôi có thể chuyển danh sách hóa đơn và số lượng cuộc gọi tối thiểu (số tối ưu) để truy xuất dữ liệu?

Trả lời

4

Bạn có thể sử dụng các truy vấn với tham gia tìm nạp trước để có được toàn bộ đồ thị đối tượng vào bộ nhớ:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 
+1

Có giải quyết vấn đề trong một truy vấn. Hạn chế duy nhất là sản phẩm Descartes của tất cả các bảng này có thể rất lớn không? – Cris

+1

Thật vậy. Tuy nhiên, với phương pháp này bạn luôn có thể chọn các liên kết để tìm nạp ngay lập tức và tải nào một cách lười biếng.Sau đó, bạn có thể sử dụng kích thước hàng loạt, như Simon đề xuất, để tăng tốc độ tìm nạp cho những người lười biếng. –

+1

+1 cho ví dụ mà tôi đã thêm vào câu trả lời của mình. –

4

Bạn có thể xem xét batch fetching cho các dòng hóa đơn của mình và tìm nạp mong muốn cho nhiều liên kết như Khách hàng.

Điều này sẽ không đưa bạn xuống một cuộc gọi DB, nhưng nếu bạn điều chỉnh kích thước hàng loạt của mình để vượt quá số dòng trung bình của mỗi loại trong một hóa đơn, bạn có thể giảm xuống một loại trên mỗi loại.

Bạn cũng có thể truy vấn sử dụng JPQL/HQL và dứt khoát Truy xuất-gia nhập dòng (as Russ decribes), nhưng bạn sẽ có được một kết quả lớn hơn thiết hơn bạn sẽ có một loạt phương pháp lấy:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 

Nếu kích thước của dữ liệu thô được chuyển chứng minh là quá cao, bạn có thể vô hiệu hóa tìm nạp một cách rõ ràng bằng cách xóa "tìm nạp" khỏi truy vấn ở các vị trí có liên quan. Lưu ý rằng có vấn đề về bảo trì khi sử dụng JPQL vì trình biên dịch không thể kiểm tra tất cả tên thuộc tính cho bạn và nếu tìm nạp được tắt cho tất cả các liên kết thì truy vấn là chi phí ròng. Bạn có thể bắt đầu với việc tìm nạp hàng loạt nếu hiệu suất không phải là vấn đề ngay lập tức.

+0

bạn đưa tôi đi đúng hướng (unfortunatelly tôi không thể cung cấp cho bạn một phiếu lên kể từ khi tôi đang không được phép nêu ra) .Cảm ơn bạn – Cris

+1

Các truy vấn được đặt tên có thể được sử dụng để giải quyết vấn đề về tên thuộc tính - chúng có thể được kiểm tra dễ dàng trong một bài kiểm tra đơn vị. Truy vấn thời gian chạy chỉ là để thu nhỏ ví dụ - truy vấn được đặt tên phải luôn được sử dụng. –

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