Pierre Duplouy
Pierre Duplouy

Reputation: 2425

Cache all queries by default using hibernate/ehcache?

Our application handles read-only data, so we are considering using Hibernate query cache features (implemented by ehcache) on all queries.

So far we enabled both second level and query caches:

<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>

And then told hibernate that each query was cacheable:

query.setHint("org.hibernate.cacheable", true);

I can identify two drawbacks from this approach:

Is there any way to achieve this, i.e. caching all queries, using only configuration files?

Thank you!

Upvotes: 0

Views: 1188

Answers (3)

tom
tom

Reputation: 2310

Accepted answer is incorrect. Many apps need to cache 100% of named queries. And all apps that I know would benifit from default to cache all and some hint to exclude a given query.

So to do it, without the requested defaults, after enabling query cache in ehcache/hibernate, you will need to add this hint to all queries:

@NamedQuery(name = "OrderState.findByFqn", query = "select os from OrderState os where os.fqn = ?1", hints = @QueryHint(name = "org.hibernate.cacheable", value = "true")),

Then also key is to test, so many little things can break the real ehcaching. "real" meaning not just PK's but rather all object attributes/ nested ones, etc... So do that, you simply add this hiberante interceptor, turn it on with your system tests/ public static flag, then any SQL generated by hibernate to the DB will throw an error which you can catch and display in your web UI:

public class SqlCommentStatementInspector implements StatementInspector {
 
public static final String UNEXPECTED_SQL_GENERATED_MESSAGE = "UNEXPECTED SQL GENERATED";

private static final Log log = LogFactory.getLog(SqlCommentStatementInspector.class);


@Override
public String inspect(String sql) {
        
    if(StringUtils.isNotEmpty(sql) && SystemTest.ERROR_ON_SQL_B)
        throw new RuntimeException(UNEXPECTED_SQL_GENERATED_MESSAGE + ": " + sql);
    else
        return sql;       
}

}

The inteceptor is not confiruable by Spring

Upvotes: 0

Sebastien Tardif
Sebastien Tardif

Reputation: 387

It makes sense in my app to be able to cache all queries. I have an application so big, and old, that it end-up to duplicate lot of queries even during the same transaction. That app will run way faster and use not much more memory if it could cache query result of all queries during the request. Let say to simplify, I set the cache for 10 seconds, then I will get my application to be significantly faster.

Upvotes: 0

Dragan Bozanovic
Dragan Bozanovic

Reputation: 23562

No, there is not, because that would not make much sense (or better said, it would not be useful in 99.99% of the use cases).

There is always a different entry in the cache for each combination of the query and the input parameters (bind variables).

The query cache should be enabled for queries which select from entities (tables) that are changed (inserted into, updated, deleted from) rarely and for which there will not be a large number of combinations of different input parameters.

Upvotes: 1

Related Questions