Hi !
I'd like to use Hibernate 3 filters for temporal data. The problem is: the filter only gets applied to an element if this element is the top-level element in a query or a load. The filter is NOT applied if the element is eagerly fetched or is lazily fetched by navigating a collection. Is this a bug or am I missing something here ?
I've tried to get this to work for some time now. I even discovered a post (as yet unanswered) by lovkiys on 30 Aug. who seems to have the same problem (title: "Hibernate 3 filters for a object graph loading").
The following example demonstrates the problem.
There are two classes: Parent and Child. Parent contains a collection (bag) of Child objects. I've inserted a single Parent with three Child objects into the database in a previous session. When I enable the filter and then load all Child objects from the database with the query "from Child" I get only one Child object. This is expected since the filter only matches one of the three children. Fine.
But when I load (or get or query) the Parent element it has in it's collection of child objects all three children ! I would have expected only one Child here as well. It is evident from the generated SQL (show_sql=true) that the filter clause is not included in this second case. But why not ?
Changing the fetching strategy from lazy to eager fetching didn't make any difference.
Help is very much appreciated.
Thanks, joak
Hibernate version:
3.0.5 (also tried 3.1beta2: same problem)
Mapping documents:
Code:
<hibernate-mapping>
<class name="histest.Parent" table="PARENT">
<id name="id">
<column name="ID" not-null="true"/>
<generator class="native" />
</id>
<property name="name" />
<bag name="children" cascade="all" lazy="false">
<key column="PARENT_ID" />
<one-to-many class="histest.Child" />
</bag>
</class>
<class name="histest.Child" table="CHILD">
<id name="id">
<column name="ID" not-null="true"/>
<generator class="native" />
</id>
<property name="name" />
<property name="validFrom" />
<property name="validTo" />
<filter name="effectiveDate" condition=":asOfDate BETWEEN validFrom AND validTo" />
</class>
<filter-def name="effectiveDate">
<filter-param name="asOfDate" type="date" />
</filter-def>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
// Note: a single parent with three children has been inserted into the db
// in another session.
// Enable filter for current date (only one child matches)
Filter filter = session.enableFilter("effectiveDate");
filter.setParameter("asOfDate", new Date());
// Load all children. Only one is returned since filter is active.
List<Child> children = (List<Child>)session.createQuery("from Child").list();
System.out.println("children.size()="+children.size());
// Load parent with children. Parent's child collection should contain only
// one child (but in fact it contains all three!)
parent = (Parent) session.load(Parent.class, parentId);
System.out.println("parent.getChildren().size()="+parent.getChildren().size());
Output on STDOUT:Code:
children.size()=1
parent.getChildren().size()=3
Name and version of the database you are using:HSQLDB 1.7.3.3 (also tried Firebird 1.5: same problem)
The generated SQL (show_sql=true):Code:
Hibernate: select child0_.ID as ID1_, child0_.name as name1_, child0_.validFrom as validFrom1_, child0_.validTo as validTo1_ from CHILD child0_ where ? BETWEEN child0_.validFrom AND child0_.validTo
Hibernate: select parent0_.ID as ID0_0_, parent0_.name as name0_0_ from PARENT parent0_ where parent0_.ID=?
Hibernate: select children0_.PARENT_ID as PARENT5_1_, children0_.ID as ID1_, children0_.ID as ID1_0_, children0_.name as name1_0_, children0_.validFrom as validFrom1_0_, children0_.validTo as validTo1_0_ from CHILD children0_ where children0_.PARENT_ID=?