1) Caching read-only data is a good thing, is it not?
2) If it's a read-only transaction, why not replicate when data is fetched?
3) What's stored is up to Hibernate. What's replicated is up to JBoss Cache. To be honest, I don't really know, though.
Caching read-only data is a good thing if it is done locally, but i don´t understand why should we replicate them to all nodes in the cluster.
Scalability and good performances can be achieved only if we reduce the amount of informations sent to the channel. So imagine that a transaction performs a SELECT * FROM T, where T is a table containing 1.000.000 of records, this transaction would produce an incredible and not necessary traffic on the communication channel, decreasing scalability and performances of the all cluster. isn´t it?
Please read the general hibernate documentation on the second level cache, as all JBossCache does is provide a replicated data store. Typically you lazily load a result set that large, unless you have massive amounts of memory.
Still, it's a valid question. Even if we're only talking a single entity, the fact that node A read in the entity doesn't imply that node B wants to have it in memory. Replicating it takes resources.
For sure I don't see why we'd replicate this if the cache is in INVALIDATE mode rather than REPL. A quick look at the code in both HEAD and the 1.x branch leads me to believe we do.
For the issue of invalidating, see http://jira.jboss.com/jira/browse/JBCACHE-1027 .
If we could get INVALIDATE_SYNC working well for entities (i.e. stuff we're working on to allow a different cache for the query cache, which doesn't like INVALIDATE), then IMO the CacheMode attribute on the cache will provide sufficient control; i.e. if you want the entity to replicate when Hibernate caches it, use REPL_SYNC; if you don't, use INVALIDATE_SYNC.
- REPLICATION mode replicates everything is put inside the cache. This is bad because replicates everything, also objects that have not been modified, generating unnecessary traffic.
- INVALIDATION mode tags objects that are out of date. This is bad because objects have to be reloaded into cache accessing the database.
I think it would be better an hybrid approach: simply replicate changes.
I agree that what or how things are replicated, cached, or invalidated should be entirely up to you. However, there are many valid reasons to replicate read-only data to all nodes of the cache. And there are just as many good reasons to use an invalidation strategy.
To label one approach as "bad" or not sounds really ignorant.
I just tested it, and for the head of the JBC trunk at least, setting a Option with setCacheModeLocal(true) before the putForExternalRead call prevents replication for that call. So, JBC exposes an API to allow the behavior you want.
If you want this behavior for Hibernate's use of JBC as a 2nd level cache, then you need to post a feature request on the Hibernate project. This could be controlled on a per-SessionFactory basis via a Hibernate configuration property. Configuring it on a per-entity type would be a lot more complex, if it's doable at all.