views:

397

answers:

2

In my grails application, some of my domain classes will never be changed by Users.

However, some maintenance work is sometimes necessary, and administrator should be able to create/edit few instances from time to time (let's say twice a year).

I would like to set a read-only 2nd level cache strategy for these domain classes (static mapping = { cache usage: 'read-only' } ) AND I would like to be able to 'disable' (in very particular situations) the read-only strategy in order to udate some instances via Grails scaffolding edit view.

Is it possible? What do you advise me to do?

EDIT: The solution I am implementing is a mix of Pascal and Burt answers (see comments). Both answers are great and helpful. So I got a dilemna for choosing the accepted answer! Anyway, thank you.

+2  A: 

It's probably possible but most likely non-trivial. I'd go with direct inserts using groovy.sql.Sql. You lose validation, but you could create instances and validate them but not call save(). Then do the SQL inserts if they're ok, e.g.

def thing = new Thing(params)
if (thing.validate()) {
   new Sql(dataSource).executeInsert(
             "insert into thing(name) values(?)", [params.name])
}
else {
   // report validation error
}
Burt Beckwith
Thx for your answer. Inserting new objects will work but when updating existing objects, I will need to "flush" the 2nd level cache right? (because otherwise Users will never see the changee). Do I need to use the evict() method for that?
fabien7474
Yes, excellent point. Add "def sessionFactory" to your service and call sessionFactory.evict(YourDomainClass) to clear the 2nd-level cache after an insert.
Burt Beckwith
+3  A: 

I would perform the update on the given entities using pure SQL and then make the required evict() method calls on the SessionFactory to remove the specific entities from the 2nd level cache. Note that you may have to remove entities from collections also with evictCollection(). Check this nice blog post for details on eviction.

Encapsulate all this in services (e.g. wipeBooksFromGlobalCache()) than admins can call in the very particular situations you are mentioning.

Pascal Thivent
Hi Pascal. I will certainly need to flush the 2nd level cache using the evict() method. But once evicted, will I be able to update the existing instance with read-only cache strategy?
fabien7474
@fabien7474 A read-only cache means that it isn't updated, not that entities are read-only and can't be updated. In other words, you can 1. update the entities and 2. evict() them so that they will be reloaded in the 2nd level cache (i.e. to make changes "visible").
Pascal Thivent
Thx a lot! I got it!
fabien7474
@Pascal. I have tested to update domain instances having a read-only cache strategy. But it really seems that you cannot update entities since I got the following message:ERROR cache.ReadOnlyCache - Application attempted to edit read only item: com.irofoot.MatchEvent#17595 ERROR errors.GrailsExceptionResolver - Can't write to a readonly object
fabien7474
@fabien Hmm, my bad then, you'll need to use pure SQL (I did this in the past, wasn't sure anymore, but I don't have any doubts about the `evict()` part). I'll update my answer.
Pascal Thivent