2012-01-25 38 views
13

Có một lớp Offertùy chọn mối quan hệ với lớp Article. Vì vậy, một số tài sản bài viết cung cấp có giá trị null.Hibernate/JPA: Cách buộc tham gia ngầm để sử dụng LEFT OUTER JOINS

Nếu tôi sử dụng câu lệnh sau, mọi thứ đều hoạt động tốt. Tôi nhận được tất cả các đề nghị, ngay cả những đề nghị không có bài viết.

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR a.nummer = '123456' 

Nếu tôi thay đổi tuyên bố:

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

tôi đã chỉ những Mời có điều khác biệt so với NULL. Đó là bởi vì ký hiệu cho các kết nối ngầm định (o.article.nummer) buộc một tham gia bên trong.

Có khả năng buộc các kết nối bên ngoài bên trái vào các kết nối ngầm định (chú thích hướng dẫn hoặc điều gì đó khác) không? Nếu có cơ hội tôi có thể sử dụng một dạng ngắn như thế này:

SELECT o FROM Offer o 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

Trả lời

3

Bạn có thể thử đặt @Fetch(FetchMode.JOIN) vào thuộc tính Điều. Tuy nhiên, đây là một chú thích Hibernate.

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

//... 

@ManyToOne 
@Fetch(FetchMode.JOIN) 
Article article; 
+0

đối với tôi điều này không giải quyết được vấn đề! –

+0

Tôi không biết điều này sẽ giải quyết vấn đề như thế nào.AFAIK Fetchmode chỉ xác định cách lấy dữ liệu để khởi tạo đối tượng trong bộ nhớ, chứ không phải cách thực hiện các phép nối trong một truy vấn. –

1

Theo như tôi có thể đào, Hibernate không phục vụ một cách để thay đổi hình thức ngầm mặc định của hiệp hội tham gia cho một truy vấn HQL.

Các giải pháp tốt nhất tôi có thể tìm cho bản thân mình là:

  • Xây dựng truy vấn với thông tin tham gia rõ ràng;
  • Sử dụng tiêu chí, có lẽ là tốt nhất cho xây dựng truy vấn động.
+0

OP không nói rằng có bất cứ điều gì năng động. Tôi đã bỏ lỡ một cái gì đó? –

+0

Cách sử dụng '0212' và '123456' đề xuất các thay đổi truy vấn trong thời gian chạy. Một trong những giải pháp mà tôi đã tìm thấy cho việc "sử dụng đúng tham gia SQL" đã sử dụng API tiêu chí thay thế. Và nó cảm thấy tự nhiên hơn. –

+0

API tiêu chí thường phức tạp hơn để sử dụng và ít mạnh mẽ hơn như HQL. Nếu chỉ có giá trị thay đổi, chỉ cần đặt các tham số vào truy vấn. Điều này không thực sự "động", nó được parametrized. –

0

Trước hết, nếu bạn cố gắng sử dụng o.article.nummer thay vì a.nummer, tôi tin rằng nó sẽ đặt thêm mệnh đề WHERE với tham gia bên trong. Thre là không có cách nào để nói một cách rõ ràng tham gia trái. Tuy nhiên, bạn tự xác định nó trong truy vấn nên chỉ cần sử dụng thực thể được nối từ bí danh a.number = '23456'.

Vì bạn biết trường này là vô giá trị, bạn không thể sử dụng = giống như bạn không thể sử dụng = trong SQL trên các trường có thể rỗng. Thay vì sử dụng liên hiệp để chuyển đổi các giá trị NULL cho một chuỗi rỗng cho mục đích này:

SELECT o FROM Offer o 
    LEFT OUTER JOIN o.article a 
    LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' 
     OR COALESCE(a.nummer,'') = '123456' 
0

Tôi đã có một vấn đề tương tự: Tôi có một số loại GeneralFacility bảng được trong đó có một cột SpecificType. Không phải tất cả các cơ sở đều có kiểu này và khi SpecificType được kết nối bên trong trên các mục nhập GeneralFacility-Table mà không có một kiểu cụ thể nào nằm dưới bảng.

tôi giải quyết vấn đề bằng cách đặt

@Fetch(FetchMode.SELECT) 

bên cạnh @ManyToOne line trong mô hình. Loại bây giờ được tìm nạp trong một truy vấn riêng biệt và nếu điều đó không trả về kết quả nào của truy vấn GeneralFacility KHÔNG bị loại bỏ.

+0

Tôi đoán điều này chỉ áp dụng khi bạn tìm nạp thực thể, ví dụ: sử dụng 'session.get'. Khi bạn cần tài sản trong một truy vấn HQL, nó không có ảnh hưởng xa như tôi biết. –

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