Hi,
I have two cached queries that return a collection of the same type of object.
The first query returns a subset of an association, and then the second query returns a different subset of the same association.
The problem is that there is only one CollectionCacheEntry in the cache, and it gets overridden by the second query.
* Run a cached query to return all sales for a given user that have id > 10.
* Hibernate checks to see if the query is in the StandardQueryCache.
* It is not, so the query runs and returns a result set.
* The result set (the ids of the sales > 10) is saved as a CollectionCacheEntry in the cache. The key being the User.
Code:
Transaction tx = session.beginTransaction();
tx = session.beginTransaction();
String hql = "FROM SalesUser su " +
"LEFT JOIN FETCH su.sales s" +
" WHERE su.id = :id " +
" AND s.id > 10 ";
Query q = session.createQuery(hql);
q.setInteger("id", 286);
q.setReadOnly(true);
q.setCacheable(true);
Set<SalesUser> ts = new HashSet<SalesUser>();
for (Object suTemp: q.list()) {
ts.add((SalesUser)suTemp);
}
for (SalesUser su: ts) {
for (Sales s: su.getSales()) {
System.out.println("Found sales:" + s.getId());
}
}
tx.commit();
KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[10,11,12,13,20,21,22,23]* Run another cached query to return all sales for the same user that have id > 20.
* Hibernate checks to see if the query is in the StandardQueryCache.
* It is not, so the query runs and returns a result set.
* The result set (the ids of the sales > 20) is saved as a CollectionCacheEntry in the cache. The key being the same User.
* This replaces the CollectionCacheEntry returned from the first query.
Code:
Transaction tx = session.beginTransaction();
tx = session.beginTransaction();
String hql = "FROM SalesUser su " +
"LEFT JOIN FETCH su.sales s" +
" WHERE su.id = :id " +
" AND s.id > 20 ";
Query q = session.createQuery(hql);
q.setInteger("id", 286);
q.setReadOnly(true);
q.setCacheable(true);
Set<SalesUser> ts = new HashSet<SalesUser>();
for (Object suTemp: q.list()) {
ts.add((SalesUser)suTemp);
}
for (SalesUser su: ts) {
for (Sales s: su.getSales()) {
System.out.println("Found sales:" + s.getId());
}
}
tx.commit();
KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[20,21,22,23]* Run the first cached query to return all sales for a given user that have id > 10.
* Hibernate checks to see if the query is in the StandardQueryCache.
* It is, so it uses the CollectionCacheEntry for the User object.
* The result set (the ids of the sales > 20) is returned for a query that is supposed to return the sales with ids > 10!
Code:
Transaction tx = session.beginTransaction();
tx = session.beginTransaction();
String hql = "FROM SalesUser su " +
"LEFT JOIN FETCH su.sales s" +
" WHERE su.id = :id " +
" AND s.id > 10 ";
Query q = session.createQuery(hql);
q.setInteger("id", 286);
q.setReadOnly(true);
q.setCacheable(true);
Set<SalesUser> ts = new HashSet<SalesUser>();
for (Object suTemp: q.list()) {
ts.add((SalesUser)suTemp);
}
for (SalesUser su: ts) {
for (Sales s: su.getSales()) {
System.out.println("Found sales:" + s.getId());
}
}
tx.commit();
KEY: my.package.SalesUser.sales#286.my.package.SalesUser.sales
CONTENT: CollectionCacheEntry[20,21,22,23]Error: The result set should be [10,11,12,13,20,21,22,23]
Sales User Object MappingCode:
<hibernate-mapping package="my.package">
<class name="SalesUser" table="sales_user">
<id name="id" column="userId" type="long">
<generator class="native"/>
</id>
<set name="sales" inverse="true">
<cache usage="nonstrict-read-write"/>
<key column="salesPersonId"/>
<one-to-many class="Sales"/>
</set>
</class>
</hibernate-mapping>
Sales Object MappingCode:
<hibernate-mapping package="my.package">
<class name="Sales" table="sales">
<id name="id" column="salesId" type="long">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
Is there a way to ensure that the key used for the CollectionCacheEntry is uniqely associated with a parameterized cached query so that is is only returned when that specific query is executed?
Thanks,
-Erik