Hi,
I have a problem with native (sql) scalar queries and caching. Suppose caching is enabled as follows:
Code:
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
When using native hibernate api like this:
Code:
SQLQuery query = getSession().createSQLQuery("select count(*) from TEST_ENTITY");
query.setCacheable(true);
query.list();
I get the following error:
Quote:
java.lang.ClassCastException: java.lang.Integer
at org.hibernate.cache.StandardQueryCache.put(StandardQueryCache.java:104)
at org.hibernate.loader.Loader.putResultInQueryCache(Loader.java:2212)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2163)
at org.hibernate.loader.Loader.list(Loader.java:2121)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
The ClassCastException occurs because StandardQueryCache.put is called with Type[] returnTypes = []
The solution using the hibernate api is simple, just specifiy the scalar type as follows:
Code:
SQLQuery query = getSession().createSQLQuery("select count(*) as COUNTALL from TEST_ENTITY");
query.setCacheable(true);
query.addScalar("COUNTALL", new IntegerType());
query.list();
However I did not find an easy way to provide the scalar-type using hibernate entity manager.When using entity-manager like this (I also get ClassCastException in StandardQueryCache.java:104)
Code:
Query query = entityManager.createNativeQuery("select count(*) from Users");
query.setHint("org.hibernate.cacheable", "true");
query.getSingleResult();
I tried to provide a scalar type using the following result-set-mapping:
Code:
<sql-result-set-mapping name="rsm">
<column-result name="COUNTALL" />
</sql-result-set-mapping>
Query query = entityManager.createNativeQuery("select count(*) AS COUNTALL from Users", "rsm");
query.setHint("org.hibernate.cacheable", "true");
query.getSingleResult();
However now I get a NullPointerException in StandardQueryCache.java:80:
Quote:
java.lang.NullPointerException
at org.hibernate.cache.StandardQueryCache.put(StandardQueryCache.java:80)
at org.hibernate.loader.Loader.putResultInQueryCache(Loader.java:2187)
at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2138)
at org.hibernate.loader.Loader.list(Loader.java:2096)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:289)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1695)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:142)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:152)
The NPE happens because StandardQueryCache.put is called with Type[] returnTypes = [null]
I made it working with the following (very unsatisfying) code:
Code:
Query query = entityManager.createNativeQuery("select count(*) AS COUNTALL from Users");
query.setHint("org.hibernate.cacheable", "true");
HibernateQuery hibernateQuery = (HibernateQuery)query;
SQLQuery sq = (SQLQuery)hibernateQuery.getHibernateQuery();
sq.addScalar("COUNTALL", new IntegerType());
query.getSingleResult();
So the question is, how can I specify scalars (using resultsetmapping) for cached native queries using hibernate entity manager?
lg,
daniel