Search code examples
javahibernateormnhibernate-mappinghibernate-filters

Hibernate enableFilter not working when loading entity by id


I have 3 classes:

  • Event
  • PublicEvent extends Event
  • PersonalEvent extends Event

my hibernate mapping file is somethings like bellow. i wanna add one filter for PersonalEvent and before loading this object, i was enabled that's filter. but this is not working. my hibernate version is 4.3.11.Final.

Event.hbm.xml

<hibernate-mapping>
    <class name="org.calendar.Event">
        ...
        <filter name="personalEventAuthorize" condition="person_ID = :personId" />
    </class>
    <joined-subclass name="org.calendar.PersonalEvent" extends="org.calendar.Event">
        <key column="id" property-ref="id" />
        ...
        <many-to-one name="person" column="person_ID" entity-name="org.person.Person" />
     </joined-subclass>
     <joined-subclass name="org.calendar.PublicEvent" extends="org.calendar.Event">
        <key column="id" property-ref="id" />
        ...
     </joined-subclass>
     <filter-def name="personEventAuthorize">
        <filter-param name="personId" type="integer" />
     </filter-def>
</hibernate-mapping>

PersonalEventRepository

@Override
public PersonalEvent load(Long id) {
    Filter filter = getSession().enableFilter("personEventAuthorize");
    filter.setParameter("personId", getAuthenticatedPersonId());
    return super.loadById(id);
}

hibernate generated SQL Query without my filter. what is my problem? why hibernate can not enabled filter for joined-subclass? thanks for all...


Solution

  • This is not a bug, it's the intended behavior. I updated the Hibernate User Guide to make it more obvious.

    The @Filter does not apply when you load the entity directly:

    Account account1 = entityManager.find( Account.class, 1L );
    Account account2 = entityManager.find( Account.class, 2L );
    
    assertNotNull( account1 );
    assertNotNull( account2 );
    

    While it applies if you use an entity query (JPQL, HQL, Criteria API):

    Account account1 = entityManager.createQuery(
        "select a from Account a where a.id = :id", 
        Account.class)
        .setParameter( "id", 1L )
    .getSingleResult();
    assertNotNull( account1 );
    try {
        Account account2 = entityManager.createQuery(
            "select a from Account a where a.id = :id", 
            Account.class)
        .setParameter( "id", 2L )
        .getSingleResult();
    }
    catch (NoResultException expected) {
        expected.fillInStackTrace();
    }
    

    So, as a workaround, use the entity query (JPQL, HQL, Criteria API) to load the entity.