2011-08-02 26 views
17

Tengo una relación padre/hijo entre dos tablas y la asignación correspondiente en mis clases de Java. Las tablas se parecen más o menos lo siguiente:anotación para filtrar los resultados de una asociación de @OneToMany

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

y el código de 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; 
} 

Esto funciona bien, pero me gustaría añadir un filtro en las filas que recuperar de la tabla secundaria. La consulta que se genera el siguiente aspecto:

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

y me gustaría que fuera:

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

El filtro adicional no sería más que un nombre de columna y un valor no modificable. ¿Hay alguna manera de hacerlo utilizando anotaciones de hibernación?

He visto @JoinFormula, pero con eso siempre tengo que hacer referencia al nombre de una columna de la tabla padre (en el atributo name de JoinFormula).

Gracias de antemano por cualquier consejo.

+0

Curioso, ¿por qué no simplemente pasarlo como un parámetro? 'donde a_ref =? y otro =? '. El valor pasado puede ser codificado si eso es lo que necesita hacer (sugiero utilizar un sistema de propiedades configurables). – ADTC

Respuesta

26

No es compatible con JPA, pero si utiliza hibernación como proveedor JPA, puede usar la anotación @FilterDef y @Filter.

Hibernate Core Reference Documentation

Hibernate3 tiene la capacidad de pre-definir criterios de filtro y adjuntar esos filtros, tanto a nivel de clase y un nivel de colección. Un criterio de filtro le permite definir una cláusula de restricción similar al atributo existente "donde" disponible en la clase y varios elementos de colección . Sin embargo, estas condiciones de filtro pueden ser parametrizadas. La aplicación puede decidir en tiempo de ejecución si se deben habilitar ciertos filtros y cuáles deberían ser sus valores de parámetro . Los filtros se pueden usar como vistas de bases de datos, pero están parametrizados dentro de la aplicación.

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

Gracias, funciona bien. Aunque es un poco molesto que tengas que habilitarlo dinámicamente (siempre lo habilitaré). ¡Viviré con eso! – Xavier

+0

No hay un método upwrap en entityManager :( –

+1

Lo sentimos, solo está disponible desde JPA 2.0. Http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#unwrap(java.lang. Clase) –

0

con JPA 1 Se puede utilizar la solución aportada pero el cambio Separar a getDelegate que ser así

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

y va a trabajar.

0

Si yo soy la comprensión de la pregunta correcta, hay una manera de hacer esto con anotaciones javax.persistence (He utilizado este en un ManyToOne mí mismo, y adaptado la respuesta de here):

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

Nota del citas individuales en el nombre de columna referenciado, este es el valor que está buscando.

Más información here.

Cuestiones relacionadas