Grails: обновление одного объекта в домене ".save" Vs ".executeUpdate" - PullRequest
4 голосов
/ 02 октября 2010

Мне интересно, какой самый эффективный способ обновления одного значения в классе домена из строки в базе данных.Допустим, класс домена имеет более 20 полей

    def itemId = 1

    def item = Item.get(itemId)
    itemId.itemUsage += 1
    Item.executeUpdate("update Item set itemUsage=(:itemUsage) where id =(:itemId)", [usageCount: itemId.itemUsage, itemId: itemId.id])

    vs

    def item = Item.get(itemId)
    itemId.itemUsage += 1
    itemId.save(flush:true)

Ответы [ 4 ]

7 голосов
/ 02 октября 2010

executeUpdate более эффективно, если размер и количество необновленных полей велики (и это субъективно). Именно поэтому я тоже часто удаляю экземпляры, выполняя команду «delete from Foo, где id = 123», поскольку мне кажется расточительным загружать экземпляр полностью, просто вызывая для него delete ().

Если в вашем доменном классе есть большие строки и вы используете подход get () и save (), то вы без необходимости сериализуете все эти данные из базы данных на веб-сервер дважды, когда все, что вам нужно изменить, это одно поле.

Эффект на кэш 2-го уровня необходимо учитывать, если вы используете его (и если вы много редактируете экземпляры, то, вероятно, не должны). С executeUpdate он сбрасывает все экземпляры, ранее загруженные с помощью get (), но если вы обновите с помощью get + save, если сбрасывает только этот один экземпляр. Это ухудшается, если вы кластеризуетесь, поскольку после executeUpdate вы очищаете все кэши узлов кластера, а не очищаете один экземпляр на всех узлах.

Лучше всего сравнить оба подхода. Если вы не перегружаете базу данных, возможно, вы преждевременно оптимизируете, и лучше всего использовать стандартный подход, чтобы сохранить простоту при решении других проблем.

4 голосов
/ 02 октября 2010

Если вы используете get / save, вы получите максимальное преимущество от кэша гибернации.executeUpdate может вызвать больше операций выбора и обновления.

Способ, которым executeUpdate взаимодействует с кэшем гибернации, имеет значение здесь.Кэш гибернации становится недействительным на executeUpdate.При следующем доступе к этому Предмету после executeUpdate будет иметь для доступа к базе данных (и, возможно, больше, я думаю, что hibernate может сделать недействительными все элементы в кэше).включите ведение журнала отладки для org.hibernate в вашем Config.groovy и проверьте вызовы SQL.

3 голосов
/ 02 октября 2010

Я думаю, что они равны. Оба выпускают 2 вызова sql.

Более эффективным будет только одно обновление

Item.executeUpdate("update Item set itemUsage=itemUsage+1 where id =(:itemId)", [ itemId: itemId.id])
1 голос
/ 28 августа 2014

Вы можете использовать атрибут отображения dynamicUpdate в своем классе Item:

http://grails.org/doc/latest/ref/Database%20Mapping/dynamicUpdate.html

Если эта опция включена, ваш второй способ обновления одного поля с помощью Gorm будет таким же эффективным, как и первый.

...