Как использовать GORM для автоматического обновления группы объектов

Я использую автономный GORM (groovyVersion = '2.0.8', grailsVersion = '2.2.4', gormVersion = '1.3.7', h2Version = '1.3.170') и имею базу данных объектов, которые будут часто модификация.

Эти объекты сгруппированы по одному свойству «запись» и имеют другое свойство «process_flags», которое мне нужно обновить. Я хочу обновить все настройки process_flag группы объектов, определенных с помощью одной и той же записи. (Это укажет другим процессам, что я обрабатываю эту группу объектов.)

В настоящее время я пробую следующий код:

List<Item>  res = null
int triesRemaining = 10 // try locking a group this many times
while (res==null && triesRemaining > 0) {
  Item firstItem = Item.findByProcessFlags(Item.ProcessFlags.NEW)
  if (firstItem==null) return null
  res = Item.findAllByEntry(firstItem.entry)
  try {
    Item.withTransaction {transStatus->
      res.each {it->
        if (it.processFlags != Item.ProcessFlags.NEW) {
          throw new StaleObjectStateException(Item.class.toString(),it.id)
        }
        it.processFlags = Item.ProcessFlags.IN_PROCESS
        it.save(flush:true)
      }
    }
  } catch (HibernateOptimisticLockingFailureException e) {
    logger.debug("Caught HibernateOptimisticLockingFailureException. Trying new group.")
    res = null
    triesRemaining--
  }
return res

Это приводит к распространению исключения вверх по стеку, помеченного как возникающее в res.each и как StaleObjectStateException, хотя я предполагаю, что на самом деле это HibernateOptimisticLockingFailureException, согласно этому обсуждению: Как обрабатывать исключения GORM. Обратите внимание, что ни класс, ни метод, в котором появляется этот код, не имеют аннотации @Transactional.

Итак, мои вопросы: как лучше всего справиться с этой ситуацией в коде с частым одновременным доступом? Есть ли способ сделать это с отловом сбоя оптимистической блокировки? Или это нужно обрабатывать с помощью какой-то пессимистической блокировки? И если да, то можно ли с этим справиться с помощью динамических искателей?


person Peter N. Steinmetz    schedule 30.05.2014    source источник
comment
Следует отметить один очень важный момент. Класс PatchedDefaultEventListener, который находится в Grails, регистрирует исключение как ошибку, а затем повторно выдает его. Это отображается в журнале и немного сбивает с толку, потому что похоже на то, что исключение перехватывается дальше, но это не так. Возникающее исключение — HibernateOptimisticLockingFailureException.   -  person Peter N. Steinmetz    schedule 05.06.2014


Ответы (1)


То, что вы хотите сделать, это использовать запрос where. Метод where возвращает экземпляр DetachedCriteria, который позволяет выполнять пакетное обновление:

 Item.where { entry == firstItem.entry }
     .updateAll(processFlags: Item.ProcessFlags.IN_PROCESS)
person Graeme Rocher    schedule 01.06.2014