2011-08-02 14 views
17

Mam relacji nadrzędny/podrzędny między dwiema tabelami i odpowiednie mapowanie w moich klas Java. Tabele z grubsza wyglądać tak:adnotacja do filtrowania wyników asocjacji @OneToMany

A (ref number, stuff varchar2(4000)) 
B (a_ref number, other number, foo varchar2(200)) 

i kod Java:

@Entity 
class A { 
    @Id 
    @Column(name = "REF") 
    private int ref; 

    @OneToMany 
    @JoinColumn(name = "A_REF", referencedName = "REF") 
    private Set<B> bs; 
} 

@Entity 
class B { 
    @Id 
    @Column(name = "A_REF") 
    private int aRef; 

    @Id 
    @Column(name = "OTHER") 
    private int other; 
} 

Działa to dobrze, ale chciałbym dodać filtr na wierszach, które ja pobrać z tabeli podrzędnej. Kwerenda, która jest generowana wygląda następująco:

select a_ref, other, foo from B where a_ref = ? 

I chciałbym go mieć:

select a_ref, other, foo from B where a_ref = ? and other = 123 

Dodatkowy filtr będzie tylko nazwa kolumny i zakodowane wartość. Czy jest sposób na to, używając adnotacji hibernacji?

Spojrzałem na @JoinFormula, ale z tym zawsze muszę odwołać się do nazwy kolumny z tabeli nadrzędnej (w atrybucie name z JoinFormula).

Z góry dziękuję za radę.

+0

Ciekawi, dlaczego nie przekazać go jako parametru? 'gdzie a_ref =? i inne =? '. Wartość przekazana może zostać zakodowana na stałe, jeśli jest to potrzebne (sugerowałbym jednak użycie konfigurowalnego systemu właściwości). – ADTC

Odpowiedz

26

Nie jest obsługiwany przez JPA, ale jeśli używasz hibernacji jako dostawcy JPA, możesz użyć adnotacji @FilterDef i @Filter.

Hibernate Core Reference Documentation

Hibernate3 ma możliwość wstępnego zdefiniowania kryteriów filtrowania i przywiązują te filtry zarówno na poziomie klasy i poziomu zbiórki. Kryterium filtru umożliwia zdefiniowanie klauzuli ograniczenia podobnej do istniejącego atrybutu "where" dostępnego w klasie i różnych elementów kolekcji . Te warunki filtrowania można jednak sparametryzować. Aplikacja może wtedy w czasie wykonywania decydować, czy należy włączyć niektóre filtry i jakie powinny być ich wartości parametrów: . Filtry mogą być używane podobnie jak widoki bazy danych, ale są one sparametryzowane wewnątrz aplikacji.

Exemple

@Entity 
public class A implements Serializable{ 
    @Id 
    @Column(name = "REF") 
    private int ref; 

    @OneToMany 
    @JoinColumn(name = "A_REF", referencedColumnName = "REF") 
    @Filter(name="test") 
    private Set<B> bs; 
} 

@Entity 
@FilterDef(name="test", defaultCondition="other = 123") 
public class B implements Serializable{ 
    @Id 
    @Column(name = "A_REF") 
    private int aRef; 

    @Id 
    @Column(name = "OTHER") 
    private int other; 
} 

Session session = entityManager.unwrap(Session.class); 
session.enableFilter("test"); 
A a = entityManager.find(A.class, new Integer(0)) 
a.getb().size() //Only contains b that are equals to 123 
+0

Dzięki, działa dobrze. To trochę denerwujące, ale musisz włączyć to dynamicznie (zawsze to włączę). Będę z tym żyć! – Xavier

+0

Nie ma metody upwrap na entityManager :( –

+1

Niestety, jest dostępna tylko od wersji JPA 2.0 http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#unwrap(java.lang. Klasa) –

0

z JPA 1 można użyć dostarczonego rozwiązania, ale zmianę unwrap do getDelegate tak być

Session session = (Session)entityManager.getDelegate(); 

i to będzie działać.

0

Jeśli jestem zrozumienia prawo pytanie, istnieje sposób, aby zrobić to z adnotacjami javax.persistence (użyłem tego na ManyToOne siebie i dostosowane odpowiedź od here):

@JoinColumns({ 
    @JoinColumn(name = "A_REF", referencedColumnName = "REF"), 
    @JoinColumn(name = "B_TABLE_NAME.OTHER", referencedColumnName = "'123'")}) 
@OneToMany 
private Set<B> bs; 

Uwaga na pojedynczy Cytaty w referencedColumnName, jest to wartość, której szukasz.

Więcej informacji here.