Hibernate Filters

Hibernate3 proporciona un nuevo enfoque innovador para manejar datos con reglas de "visibilidad". Unfiltro Hibernate es un filtro global, con nombre y parametrizado que puede ser habilitado o deshabilitado para una sesión de Hibernate especifica.

Hibernate3 tiene la habilidad de predefinir criterios de filtros y unir esos filtros tanto a nivel de clase como de colección. Un criterio de filtro le permite definir una cláusula de restricción muy similar al atributo existente "where" disponible en el elemento class y en varios elementos de colección. Sin embargo, las condiciones de estos filtros se pueden parametrizar. La aplicación puede tomar la decisión en tiempo de ejecución de si los filtros deben estar habilitados y cuáles deben ser sus parámetros. Los filtros se pueden utilizar como vistas de la base de datos, pero parametrizados dentro de la aplicación.

Para utilizar los filtros, éstos se deben definir primero y luego se unen a los elementos de mapeo apropiados. Para definir un filtro, utilice el elemento  dentro de un elemento:


<filter-def name="myFilter">
    <filter-param name="myFilterParam" type="string"/>
</filter-def
>

Luego este filtro se puede adjuntar a una clase:


<class name="myClass" ...>
    ...
    <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>
</class
>

O a una colección:


<set ...>
    <filter name="myFilter" condition=":myFilterParam = MY_FILTERED_COLUMN"/>
</set
>

O incluso a ambos o múltiples de cada uno al mismo tiempo.

Los métodos en Session son: enableFilter(String filterName)getEnabledFilter(String filterName) ydisableFilter(String filterName). Por defecto, los filtros no están habilitados para una sesión dada. Los filtros deben ser habilitados explícitamente por medio del uso del método Session.enableFilter(), el cual retorna una instancia de la interfaz Filter. Si se utiliza el filtro simple definido anteriormente, esto se vería así:

session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");

Los métodos en la interfaz org.hibernate.Filter permiten el encadenamiento de métodos, lo cual es bastante común en gran parte de Hibernate.

Este es un ejemplo completo, utilizando datos temporales con un patrón efectivo de fechas de registro:


<filter-def name="effectiveDate">
    <filter-param name="asOfDate" type="date"/>
</filter-def>

<class name="Employee" ...>
...
    <many-to-one name="department" column="dept_id" class="Department"/>
    <property name="effectiveStartDate" type="date" column="eff_start_dt"/>
    <property name="effectiveEndDate" type="date" column="eff_end_dt"/>
...
    
    <filter name="effectiveDate"
            condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
</class>

<class name="Department" ...>
...
    <set name="employees" lazy="true">
        <key column="dept_id"/>
        <one-to-many class="Employee"/>
        <filter name="effectiveDate"
                condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
    </set>
</class
>

Con el fin de asegurarse de que siempre recibirá los registros efectivos actualmente, habilite el filtro en la sesión antes de recuperar los datos de los empleados:

Session session = ...;
session.enableFilter("effectiveDate").setParameter("asOfDate", new Date());
List results = session.createQuery("from Employee as e where e.salary 
> :targetSalary")
         .setLong("targetSalary", new Long(1000000))
         .list();

En el HQL anterior, aunque sólo mencionamos explícitamente una restricción de salario en los resultados, debido al filtro habilitado la consulta sólo retornará empleados actualmente activos que tengan un salario mayor a un millón de dólares.

Si quiere utilizar filtros con unión externa, ya sea a través de HQL, o bien de recuperación de carga, tenga cuidado en la dirección de expresión de la condición. Lo más seguro es configurar esto para una unión externa izquierda. Coloque el parámetro primero seguido del nombre(s) de la(s) columna(s) después del operador.

Después de definir un filtro, este se puede unir a múltiples entidades y/o colecciones cada una con su propia condición. Esto puede llegar a ser problemático cuando las condiciones son las mismas. Así que el usar  le permite definir una condición por defecto, ya sea como atributo o como CDATA:


<filter-def name="myFilter" condition="abc 
> xyz"
>...</filter-def>
<filter-def name="myOtherFilter"
>abc=xyz</filter-def
>

Esta condición predeterminada se utilizará cuando se una el filtro a algo sin especificar una condición. Esto significa que usted le puede dar una condición especifica como parte del anexo del filtro, el cual substituye la condición por defecto en ese caso en particular.

No hay comentarios.: