2009-06-12 15 views
5

Mam dwie klasy, Osobę i Firmę, pochodzące z innej Kontaktu z klasą. Są one reprezentowane polimorficznie w dwóch tabelach (osoba i firma). Uproszczone klasy wyglądać następująco:Zapytanie polimorficzne w trybie hibernacji

public abstract class Contact { 

    Integer id; 

    public abstract String getDisplayName(); 

} 

public class Person extends Contact { 

    String firstName; 
    String lastName; 

    public String getDisplayName() { 
    return firstName + " " + lastName; 
    } 

} 

public class Company extends Contact { 

    String name; 

    public String getDisplayName() { 
    return name; 
    } 

} 

Problemem jest to, że muszę złożyć zapytanie znalezieniem wszystkie kontakty z displayName zawierający pewną ciąg. Nie mogę wykonać kwerendy przy użyciu displayName, ponieważ nie jest częścią żadnej tabela. Wszelkie pomysły na temat tego zapytania?

+0

Czy można oznaczyć tę Java? –

Odpowiedz

4

Ponieważ wykonuje się konkatenację w klasie Java, nie ma mowy, że Hibernate naprawdę może ci w tym pomóc, przepraszam. Może po prostu nie zobaczyć, co robisz w tej metodzie, ponieważ w rzeczywistości nie jest to w ogóle związane z utrwalaniem.

Rozwiązanie zależy od sposobu odwzorowane dziedziczenie tych klas:

Jeśli to table-per-hierarchii można użyć tego podejścia: Napisz SQL gdzie klauzuli do kwerendy kryteriów, a następnie użyj przypadek oświadczenie:

s.createCriteria(Contact.class) 
.add(Restrictions.sqlRestriction("? = case when type='Person' then firstName || ' '|| lastName else name end")) 
.list(); 

Jeśli jest tabela per-betonu-podklasy, to jesteś lepiej pisać dwa zapytania (ponieważ to właśnie Hibernate zrobi tak).

+0

Mam go jako tabelę dla konkretnych klas. Być może najszybszym rozwiązaniem jest napisanie dwóch zapytań i połączenie ich po stronie Java. – rmarimon

2

Możesz utworzyć nową kolumnę w tabeli Contact zawierającej odpowiednią displayName, którą możesz wypełnić za pomocą Hibernacji Interceptor, aby zawsze zawierała właściwy ciąg automatycznie.

Alternatywą byłoby posiadanie dwóch zapytań, jeden dla tabeli Person i jeden dla tabeli Company, z których każdy zawiera odpowiednią logikę wyszukiwania. Być może będziesz musiał użyć natywnych zapytań, aby uzyskać szukanie połączonego ciągu znaków za pomocą zapytania LIKE (nie jestem ekspertem HQL, ale może być to możliwe).

Jeśli masz duże tabele, powinieneś pomyśleć o indeksowaniu pełnotekstowym, ponieważ zapytania LIKE '%...%' wymagają pełnego skanowania tabeli, chyba że twoja baza danych obsługuje pełne indeksy tekstowe.

1

Jeśli zmienisz właściwość displayName na odwzorowaną właściwość (ustawioną na kolumnę nazwy w firmie i na formułę, taką jak pierwsza || '' || ostatnia w osobie), wówczas można zapytać o umowę, a Hibernate uruchomi dwa zapytania zarówno z których teraz ma displayName. Otrzymasz listę dwóch list, jedną zawierającą firmy i jedną zawierającą osoby, dzięki czemu będziesz musiał je połączyć. Myślę, że musisz zapytać o pełną nazwę pakietu kontraktu lub ustawić typedef, aby powiedzieć o tym Hibernate.

Powiązane problemy