Hibernate performs useless class lookup when applying the constant conversion. For instance, in the query _SELECT p FROM Event p WHERE p.eventstart<?1_, there will be a class lookup for _ch.astorm.entities.Event_ and for _p.eventstart_ and this will occur each time the query needs to be compiled by Hibernate. There will be a warning in the logs just as mentioned in the issue HHH-11245.
The "randomess" describe described in HHH-11243 is caused by query plan caching (see HHH-4627). Hence, to reproduce the warning systematically, a "new" query needs to be given to Hibernate, which is somewhat easy if they are not parametrized. So, I set the property _hibernate.query.plan_cache_max_size_ to 40 (which will be the minimum accepted value because of the _BoundedConcurrentHashMap_ fixed parameters created in _QueryPlanCache_) and created a simple loop in each query to force renewal of the cache:
{code:java} entityManager.createQuery("SELECT p FROM Event p WHERE p.eventstart<=?1 AND p.eventend>=?2", Event.class); for(int qp=0 ; qp<40 ; ++qp) { //generate a different query each time to force the query cache plan to renew entityManager.createQuery("SELECT p FROM Event p WHERE 0="+qp); } {code}
My patch suggests transforming the method _handleDotStructure_ in _QueryTranslatorImpl_ (line 613) to:
{code:java} private void handleDotStructure(AST dotStructureRoot) { final String expression = ASTUtil.getPathText( dotStructureRoot ); final Object entity = factory.getMetamodel().entity( expression ); if( entity == null && expression.indexOf('.') != -1 ) { //avoid some useless lookups //lookup & constant transformation, if any } } {code}
This check will avoid entity lookups (because the expression _ch.astorm.entities.Event_ will cause a lookup on _ch.astorm.entities_ which will be always null), but the patterns like _p.eventstart_ will still cause IMHO a useless lookup which could probably be avoided by using the parsed HQL query.
Any suggestion is welcome. Thanks in advance. |
|