Как временно отключить стратегию гибернации кеша 2-го уровня только для чтения в Grails?

В моем приложении Grails некоторые из моих доменных классов никогда не будут изменены пользователями.

Однако иногда необходимы некоторые работы по техническому обслуживанию, и администратор должен иметь возможность время от времени создавать/редактировать несколько экземпляров (скажем, два раза в год).

Я хотел бы установить стратегию кэширования 2-го уровня только для чтения для этих классов предметной области (static mapping = { cache usage: 'read-only' }) И я хотел бы иметь возможность «отключать» (в очень конкретных ситуациях) стратегию только для чтения, чтобы обновлять некоторые экземпляры через Grails вид редактирования строительных лесов.

Является ли это возможным? Что вы мне посоветуете сделать?

EDIT: решение, которое я реализую, представляет собой смесь ответов Pascal и Burt (см. комментарии). Оба ответа хороши и полезны. Итак, у меня возникла дилемма для выбора принятого ответа! В любом случае, спасибо.


person fabien7474    schedule 10.02.2010    source источник


Ответы (2)


Вероятно, это возможно, но, скорее всего, нетривиально. Я бы использовал прямые вставки, используя groovy.sql.Sql. Вы теряете проверку, но можете создавать экземпляры и проверять их, но не вызывать save(). Затем выполните вставки SQL, если они в порядке, например.

def thing = new Thing(params)
if (thing.validate()) {
   new Sql(dataSource).executeInsert(
             "insert into thing(name) values(?)", [params.name])
}
else {
   // report validation error
}
person Burt Beckwith    schedule 10.02.2010
comment
Спасибо за ваш ответ. Вставка новых объектов будет работать, но при обновлении существующих объектов мне нужно будет очистить кеш 2-го уровня, верно? (потому что иначе Пользователи никогда не увидят измененного). Нужно ли для этого использовать метод evict()? - person fabien7474; 11.02.2010
comment
Да, отличный момент. Добавьте def sessionFactory в свою службу и вызовите sessionFactory.evict(YourDomainClass), чтобы очистить кэш 2-го уровня после вставки. - person Burt Beckwith; 11.02.2010

Я бы выполнил обновление данных сущностей, используя чистый SQL, а затем сделал необходимые вызовы evict() метода в SessionFactory, чтобы удалить определенные объекты из кеша 2-го уровня. Обратите внимание, что вам может понадобиться удалить объекты из коллекций также с помощью evictCollection(). Прочтите этот хороший пост в блоге для получения подробной информации о выселении.

Инкапсулируйте все это в сервисы (например, wipeBooksFromGlobalCache()), которые администраторы могут вызывать в очень конкретных ситуациях, которые вы упоминаете.

person Pascal Thivent    schedule 10.02.2010
comment
Привет Паскаль. Мне обязательно нужно очистить кеш 2-го уровня с помощью метода evict(). Но после исключения смогу ли я обновить существующий экземпляр с помощью стратегии кэширования только для чтения? - person fabien7474; 11.02.2010
comment
@ fabien7474 Кэш только для чтения означает, что он не обновляется, а не объекты доступны только для чтения и не могут быть обновлены. Другими словами, вы можете 1. обновить объекты и 2. вытеснить их (), чтобы они были перезагружены в кэш 2-го уровня (т. е. чтобы сделать изменения видимыми). - person Pascal Thivent; 11.02.2010
comment
Я протестировал обновление экземпляров домена со стратегией кэширования только для чтения. Но на самом деле кажется, что вы не можете обновлять объекты, так как я получил следующее сообщение: ERROR cache.ReadOnlyCache — приложение попыталось изменить элемент только для чтения: com.irofoot.MatchEvent#17595 ERROR errors.GrailsExceptionResolver — невозможно записать в объект только для чтения - person fabien7474; 11.02.2010
comment
@fabien Хм, тогда мне плохо, вам нужно использовать чистый SQL (я делал это раньше, больше не был уверен, но у меня нет никаких сомнений по поводу части evict()). Я обновлю свой ответ. - person Pascal Thivent; 11.02.2010