2011-07-02 16 views
6

Làm cách nào tôi có thể viết truy vấn Tiêu chí Hibernate, cho một siêu lớp và kiểm tra một lớp con nhất định? Hãy tưởng tượng chúng ta có các lớp sau tất cả các ánh xạ lên với Hibernate-JPA:Làm thế nào tôi có thể viết truy vấn Tiêu chí Hibernate, cho một siêu lớp và kiểm tra một lớp con nhất định?

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Bar { 
    @Id 
    @Column(name = "id") 
    private Long id; 
} 

@Entity 
@PrimaryKeyJoinColumn(name="bar_id") 
public class Foo extends Bar { 
} 

@Entity 
@PrimaryKeyJoinColumn(name="bar_id")  
public class Goo extends Bar { 
} 

Khi viết một truy vấn Tiêu chuẩn như thế này, tôi muốn, cho hiệu suất, sử dụng một trái tham gia với sub-class:

getSession() 
    .createCriteria(Bar.class) 
    .createAlias("Foo", "foo", CriteriaSpecification.LEFT_JOIN) 
    .add(Restrictions.isNotNull("foo.bar_id")) 
    .list(); 

Điều này không thành công, vì đường dẫn kết hợp "Foo" không hoạt động rõ ràng, nhưng nó sẽ minh họa những gì tôi muốn. Hoặc có cách nào khác để thực hiện loại truy vấn này không? Tôi cần truy vấn được thực hiện trên lớp cha. Nếu tôi đã có thể làm điều đó trong SQL nó sẽ trông như thế này:

select b.* 
from bar b left join foo f on f.bar_id = b.id 
where f.bar_id is not null; 

Truy vấn SQL trên là chỉ để minh họa những gì tôi muốn nói, tôi biết nó sẽ được dễ dàng hơn để sử dụng một "bình thường" tham gia trong đó trường hợp cụ thể .

Trả lời

7

Thực sự không rõ bạn muốn làm gì.

Trước hết, vì Foo kế thừa từ Bar, việc tìm kiếm các cá thể Bar sẽ tự động trả về các phiên bản Foo. Hibernate tự lo việc tham gia các bảng.

Thứ hai: truy vấn SQL của bạn thực sự lạ. Bạn đang thực hiện một phép nối trái (có nghĩa là bạn đang tìm kiếm các thanh có thể không có một liên kết foo), nhưng bạn cũng có một nơi đóng trên foo.bar_id không phải là null. Thực tế trong Điều này tạo thành một bên tham gia, và có thể được viết lại như

select b.* from bar b inner join foo f on f.bar_id = b.id 

Nếu những gì bạn muốn làm là tìm kiếm Foos, và Foos chỉ, sau đó sử dụng một tiêu chuẩn với Foo như một thực thể root:

getSession() 
    .createCriteria(Foo.class) 
    .list(); 

Bạn sẽ nhận được các trường hợp Foo, nhưng vì Foo mở rộng Bar, các cá thể Foo này cũng là các cá thể Bar. Đó là những gì thừa kế.

Bây giờ nếu bạn đang xây dựng dụ Tiêu chuẩn của bạn tự động, và nhận ra tại một số điểm mà việc tìm kiếm chỉ phải trả lại trường hợp của Foo, bạn phải sử dụng các tài sản ngầm lớp:

Criteria c = getSession().createCriteria(Bar.class, "bar") 
// ... 
if (limitToFoos) { 
    c.add(Restrictions.eq("bar.class", Foo.class)); 
} 
+0

Có, tôi biết về Truy vấn SQL, nó chỉ minh họa điểm và làm sáng tỏ câu hỏi. Truy vấn của tôi là IRL phức tạp hơn nhiều. Tuy nhiên, thêm một hạn chế cho thuộc tính lớp hoạt động hoàn hảo. Khá logic khi bạn nghĩ về nó, cảm ơn. – crunchdog

+0

'Restrictions.eq (" bar.class ", Foo.class))' là những gì tôi đang tìm kiếm - cảm ơn! – jlb

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