Hello,
In my project I have a situation which can be described with imagined example below:
Code:
@Entity
@Table(name="army")
@FilterDef(name="pupilsWithGivenBirthDate", parameters={@ParamDef( name="maxDate", type="date" ), @ParamDef( name="minDate", type="date" )})
public class SchoolTO implements PersistentEntity {
/* ... some definitions */
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
@ForeignKey(name="school_to_pupuils_fk", inverseName="pupils_to_school_fk")
@JoinColumn(name="persistent_school_id" )
@OrderBy("birth_date ASC")
@Filter(name = "pupilsWithGivenBirthDate", condition = "birthDate>= :minDate AND birthDate <= :maxDate")
private List<PupilTO> pupils = new ArrayList<PupilTO>(0); // I need to have it initialized at start..
public List<PupilTO> getPupils() {
return pupils;
}
}
@Entity
@Table(name="pupils")
public class PupilTO implements PersistentEntity {
@Column(name="birth_date", nullable=false)
private Date birth_date;
}
No within my business logic I have a session (BTW: this session is maitained by Spring framework internals... so I'm not bothering about setting it up). Now I want to get the pupils born within some given period... so I enable the filter on current session in order to limit the results:
Code:
Session currentSession = / * obtain the reference to current session */
Filter filter = currentSession.enableFilter("pupilsWithGivenBirthDate");
filter.setParameter("minDate ", new Date( /* some date */ ));
filter.setParameter("maxDate ", new Date( /* some date */ ));
Now whan I have this filter enabled than I can call to
Code:
School school = /* inittialize the school by hibernate... */
var filteredPupuils = school.getPupils() ;
Yes... so far so good.... but now I need to get the pupuils born in another period so I want to redefine the filter:
Code:
Session currentSession = / * obtain the reference to current session.. it's still the same session (!) */
currentSession.disableFilter("pupilsWithGivenBirthDate");
Filter filter = currentSession.enableFilter("pupilsWithGivenBirthDate");
filter.setParameter("minDate ", new Date( /* some other date than first time */ ));
filter.setParameter("maxDate ", new Date( /* some other date than first date */ ));
But when I call to school.getPupils() I don't get new collection of pupils but there is still collection of pupils retrived first time....
This might be in most situation the correct behaviour... The collection is lazy and after it has been initialized hibernate does not want to initialize it again... ok but what about filtering as described above?
I tried to dig into it a little bit, but I didn't find a nice solution for this. The easiest would be if I could set the ((AbstractPersistantCollection) school.getPupils()).initialized flag to false... in that case hibernate would reinitialize the collection as I wanted... but I didn't found any programatic way to do this (except maybe for hacking the sources of AbstractPersistentCollection to expose the initalized flag, but I don't want to do this of course).. what is more casting to AbstractPersistantCollection is at least not prefered way.
I also tried another dirty idea:
Code:
org.hibernate.collection.PersistentBag col = ((org.hibernate.collection.PersistentBag)school.getPupils());
SessionImplementor sess = col.getSession();
CollectionEntry ce = sess.getPersistenceContext().getCollectionEntry(col);
ce.getLoadedPersister().initialize( ce.getLoadedKey(), sess );
The query is fired agains the database, but this also fails since the collection is already initalized and does not want to read from obtained resultset (BTW: Hibernate.initalize(school) fails at the beginning since there because it checks the initalized flag of collection in the first place).
Ok enough dirty methods... Is there an way I can reinitialized the collection after enabling different filter.
The only reasonable solution which comes to my mind is to call execute HQL query (or rather use find method on HibernateTemple() since I'm using spring) but in this case I'm loosing the lightweight way of obtainting the collection by just calling school.getPupils().... so I'm loosing the benefit of annotations:(
BTW: switching to non lazy or fetching whole collection is not an option in my case since in my real project the collection is huuuuge :)