Using @Filter with @ManyToOne relationship

I am using Hibernate 3.6.7-Final and Spring 3.0.5.

I have an object like this

@Entity
public class Foo {
    @ManyToOne
    private Bar bar;
}

@Entity
public class Bar {
    @Column
    String group;
}

      

How can I use @Filter

in Foo where I want to get all Foo

that have Bar

with group = :group

? This is assumed to be a security limitation.

Trying to just set @Filter(name = "groupFilter", condition = "group = :group")

in attribute Bar

from Foo

, but that didn't work. Does hibernate have support or does the filter only work at the entity / collection level? Do I have to change all of my HQLs to add this security constraint?

0


source to share


2 answers


First you need to create a @FilterDef somewhere (this defines the available options and default condition), then define @Filter for a specific class.

Finally, you need to enable the filter on the Session object and set any required parameters. Filters are not enabled on hibernate sessions by default. You have to enable the specific ones you want after opening a session.

See section 19.1 for an example: http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/filters.html

@FilterDef(name="groupFilter", parameters={@ParamDef( name="group", type="string" )})
@Filters(
  { @Filter(name="groupFilter", condition="group = :group") }
)
public class ... {
}

      



Then somewhere in your dao code:

session.enableFilter("groupFilter").setParameter("group", group);

      

You don't need to touch any hql. When you enable a filter, all classes that have an actual @Filter defined for it will automatically apply this condition.

There are additional ways to do things for collections, and I suggest you read the documentation above. But in general, you can provide @Filter annotation classes and collection properties.

+2


source


The problem of using filters with union is @ManyToOne

as follows. I mean Hibernate 4.3.10 as this is what I should be looking at.

The corresponding SQL fragment is generated by the class org.hibernate.engine.internal.JoinSequence

, method toJoinFragment

:

/**
 * Generate a JoinFragment
 *
 * @param enabledFilters The filters associated with the originating session to properly define join conditions
 * @param includeAllSubclassJoins Should all subclass joins be added to the rendered JoinFragment?
 * @param withClauseFragment The with clause (which represents additional join restrictions) fragment
 * @param withClauseJoinAlias The
 *
 * @return The JoinFragment
 *
 * @throws MappingException Indicates a problem access the provided metadata, or incorrect metadata
 */
public JoinFragment toJoinFragment(
        Map enabledFilters,
        boolean includeAllSubclassJoins,
        String withClauseFragment,
        String withClauseJoinAlias) throws MappingException {

        ...

        final String on = join.getAssociationType().getOnCondition( join.getAlias(), factory, enabledFilters, treatAsDeclarations );

      

join.getAssociationType()

Returns CollectionType

or, depending on the relationship EntityType

.

The first means a declaration:

@OneToMany
private List<MyEntity> myEntities;

      

The latter stands for this:

@ManyToOne
private MyEntity myEntity;

      



In the first case, this method is used:

@Override
public String getOnCondition(
        String alias,
        SessionFactoryImplementor factory,
        Map enabledFilters,
        Set<String> treatAsDeclarations) {
    return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters, treatAsDeclarations );
}

      

while in the second case the method looks like this:

@Override
public String getOnCondition(
        String alias,
        SessionFactoryImplementor factory,
        Map enabledFilters,
        Set<String> treatAsDeclarations) {
    if ( isReferenceToPrimaryKey() && ( treatAsDeclarations == null || treatAsDeclarations.isEmpty() ) ) {
        return "";
    }
    else {
        return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters, treatAsDeclarations );
    }
}

      

It means that:

  • when we have a list of specified entities in the entity definition, the filter is applied unconditionally.
  • when we have one specified child entity, the filter is applied when certain conditions are (not) met.

Based on the code, I think that filters can be applied in a relationship case @ManyToOne

when:

  • in the referencing entity we are using a field that is not the primary key, or
  • The TREAT operator is used (see for example here or here )
0


source







All Articles