web-dev-qa-db-fra.com

une annotation pour filtrer les résultats d'une association @OneToMany

J'ai une relation parent/enfant entre deux tables et le mappage correspondant dans mes classes Java. Les tableaux ressemblent à peu près à ça:

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

et le code 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;
}

Cela fonctionne bien, mais j'aimerais ajouter un filtre sur les lignes que je récupère de la table enfant. La requête générée ressemble à ceci:

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

Et j'aimerais que ce soit:

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

Le filtre supplémentaire serait uniquement un nom de colonne et une valeur codée en dur. Y a-t-il un moyen de faire cela en utilisant des annotations en veille prolongée?

J'ai regardé @JoinFormula, mais avec cela, je dois toujours faire référence à un nom de colonne de la table parent (dans l'attribut name de JoinFormula).

Merci d'avance pour tout conseil.

19
Xavier

Il n'est pas pris en charge par JPA, mais si vous utilisez hibernate en tant que fournisseur JPA, vous pouvez utiliser les annotations @FilterDef et @Filter.

Documentation de référence d'Hibernate Core

Hibernate3 a la capacité de prédéfinir des critères de filtre et d’attacher Ces filtres à la fois au niveau classe et au niveau collection. Un critère de filtre Vous permet de définir une clause de restriction similaire à l'attribut "où" existant Existant dans la classe et à divers éléments de la collection . Cependant, ces conditions de filtrage peuvent être paramétrées à . L’application peut ensuite décider, au moment de l’exécution, si Certains filtres doivent être activés et quelles doivent être les valeurs de leurs paramètres . Les filtres peuvent être utilisés comme des vues de base de données, mais ils sont paramétrés dans l'application.

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
27
Joel Hudon

avec JPA 1, vous pouvez utiliser la solution fournie mais changer de dérouler pour que getDelegate soit comme ça

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

et ça va marcher.

1
MSaudi

Si je comprends bien la question, il existe un moyen de le faire avec des annotations javax.persistence (je l'ai utilisé moi-même sur ManyToOne et j'ai adapté la réponse à partir de ici ):

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

Notez les guillemets single dans le referenceColumnName, c’est la valeur que vous recherchez.

Plus d'informations ici .

0
Hans Wouters