Announcement Announcement Module
Collapse
No announcement yet.
Hibernate Filters Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Hibernate Filters

    Instead of answering questions this time I have a question .

    Currently we are implementing some kind of database limitations/security on the data returned from the database. A user should only see data related to those organisations which it has access to. So I thought to implement this with hibernate filters. The database we use is Oracle 9, Hibernate 3.2.2 and Spring 2.0.3.

    I have defined a hibernate filter in my application context

    Code:
    <bean class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean">
    	<property name="filterName" value="organisationFilter"/>
    	<property name="parameterTypes">
    		<props>
    			<prop key="organisations">string</prop>
    		</props>
    	</property>
    </bean>
    IN one of our mapping files we specified the following filter

    Code:
    <filter name="organisationFilter" condition="oge_id in (:organisations)"/>
    The problem is I use the IN keyword in the expression. As long as there is 1 oge_id it works perfectly, however when there are more then 1 I get errors. 'Not a valid number' etc.

    The issue is I defined the parameter as a String, what I actually want is to define it as a List of Longs or an long array (long[]). But for some reason I'm not being able to.

    Hopefully there is someone around here with some more experience in hibernate and filtering than me .

  • #2
    I think you can do it with a subquery:

    Code:
    <filter name="organisationFilter" condition="oge_id in (select oge_id from ... where ... )"/>
    Might still be a drag performancewise, and Oracle probably still won't work if there are more than 1000 items in the in clause.

    If you can do the query with a join instead of an "in" clause you will have a better experience. Might only be possible with a temporary table to hold the target of the join (with Oracle you have global temporary tables so you can set "delete on commit").

    Comment


    • #3
      Hmm the subselect might work. However the id's in the in clause can come from 3 different paths . Every usertype has another mapping/relation with the organisations table. It isn't my design, but I have to work with it .

      Is it possible to set the select in the in clause as the parameter? Hmm Lets create a test .

      Comment


      • #4
        A working case...

        Here is what I found to be working for a similar case:

        Hibernate filter definition (I have it in a Spring applicationContext file since I configure hibernate from spring):
        Code:
          <bean id="sessionFactory" ...>
            <property name="dataSource" ... />
            ...
            <!-- filter definitions -->
            <property name="filterDefinitions">
              <list>
                <bean class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean">
                  <property name="filterName" value="regionFilter" />
                  <property name="parameterTypes">
                    <props>
                      <prop key="regionIds">long</prop>
                    </props>
                  </property>
                </bean>
              </list>
            </property>
          </bean>
        Attaching hibernate filter to my class (this is in the class.hbm.xml file):
        Code:
          <hibernate-mapping>
            <class ...>
              <many-to-one name="region" 
                                   column="region_id"
                                   class="some.class" 
                                   ... />
              ...
              <filter name="regionFilter" condition="region_id in (:regionIds)" />
            </class>
          </hibernate-mapping>
        In java code I enable this filter and set the parameter as follows:
        Code:
          Session session = SessionFactoryUtils.getSession(m_sessionFactory, false);
          List<Long> regionIds = ...;
          if (regionIds == null) {
            // means no filtering will be performed
            session.disableFilter("regionFilter");
                
          } else if (regionIds.isEmpty()) {
            // inserting one id that should not be in the database
            regionIds.add(new Long(-1));
            session.enableFilter("regionFilter").setParameterList("regionIds", regionIds);
                
          } else {
            session.enableFilter("regionFilter").setParameterList("regionIds", regionIds);
          }

        Comment

        Working...
        X