2011-07-02 16 views
6

Jak napisać kwerendę Hibernate Criteria dla super-klasy i sprawdzić dla pewnej podklasy? Wyobraźmy sobie, że mamy następujące klasy wszystkich odwzorowanych z hibernacji-WZP:Jak mogę napisać kwerendę Hibernate Criteria dla super klasy i sprawdzić dla pewnej podklasy?

@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 { 
} 

Pisząc zapytanie Criteria tak, chciałbym, pod kątem wydajności, aby użyć lewej przyłączyć z podklasy:

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

Nie można tego zrobić, ponieważ ścieżka asocjacji "Foo" nie działa w sposób oczywisty, ale zilustruje to, co chcę. Czy istnieje inny sposób wykonywania tego typu zapytania? Potrzebuję kwerendy do wykonania nadklasy. Jeśli bym zrobił go w SQL będzie wyglądać następująco:

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

Kwerenda SQL powyżej jest tylko w celu zilustrowania tego, co to znaczy, wiem, że byłoby łatwiejsze w użyciu „normalne” przyłączyć się do tego konkretnego przypadku .

Odpowiedz

7

To naprawdę nie jest jasne, co chcesz zrobić.

Po pierwsze, ponieważ Foo dziedziczy po pasku, wyszukiwanie instancji Bar powoduje automatyczne zwracanie instancji Foo. Hibernate zajmuje się samodzielnym łączeniem tabel.

Po drugie: zapytanie SQL jest naprawdę dziwne. Robisz lewe przyłączenie (co oznacza, że ​​szukasz pasków, które mogą nie mieć skojarzonego foo), ale masz także gdzie blisko foo.bar_id nie jest null. To w rzeczywistości stanowi sprzężenie wewnętrzne i może być przepisany jako

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

Jeśli to, co chcesz zrobić, to znaleźć Foo i Foos tylko, a następnie użyć Kryteria z Foo jako podmiot root:

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

Otrzymasz instancję Foo, ale ponieważ Foo rozszerza pasek, te instancje Foo są również instancjami Bar. Oto, czym jest dziedziczenie.

Teraz, jeśli budujesz swoje wystąpienie Criteria dynamicznie, i uświadomić sobie, w pewnym momencie, że poszukiwanie musi zwrócić tylko instancji Foo, trzeba używać niejawny klasa własności:

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

Tak wiem o Zapytanie SQL, było tylko po to, by zilustrować punkt i wyjaśnić pytanie. Moje zapytanie to dużo bardziej skomplikowany IRL. Jednak dodanie ograniczenia dla właściwości klasy działa idealnie. Dość logika, kiedy się nad tym zastanowisz, dzięki. – crunchdog

+0

'Restrictions.eq (" bar.class ", Foo.class))' było tym, czego szukałem - dzięki! – jlb

Powiązane problemy