Я работал над приложением Grails и с помощью консольного плагина выполнял код во время выполнения. И при попытке сохранить объект получил исключение HibernateOptimisticLockingFailureException.Использование Grails withTransaction и пессимистического блокирования
Затем, после того, как поисковая система узнала, что использовать с Transaction, который работал нормально.
Show.withTransaction {
Show s=Show.get(1111) // any show id
s.name=s.name+'1'
s.save()
}
Я также попытался замок (пессимистический замок), который не работал и выброшенное исключение оптимистичной блокировки:
Show s=Show.lock(1111)
s.name=s.name+'1'
s.save(flush:true)
почему пессимистическая блокировка фрагмент кода не работает?
Для получения более подробной информации:
class Content {
User createdBy
User lastUpdatedBy
Date dateCreated
Date lastUpdated
static constraints = {
createdBy nullable: true
lastUpdatedBy nullable: true
}
static mapping = {
tablePerHierarchy(false)
}
}
class Show extends Content {
String name
ShowCategory category
ShowType showType
static hasMany = [images: Image]
static constraints = {
name blank: false, unique: true
showType nullable: true
images nullable: true, blank: true
category nullable: true
}
static mapping = {
table("some_table_show")
images cascade: 'all-delete-orphan'
name index: 'name_idx'
images cache: true
}
def afterInsert() {
Plug.cacheService.deleteCache() // some redis cache usage
}
def afterUpdate() {
Plug.cacheService.deleteCache() // some redis cache usage
}
}
Exception after using lock (pessimistic locking):
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.myApplication.Show] with identifier [1111]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.myApplication.Show#1111]
at com.myApplication.cacheService.deleteCache(CacheService.groovy:286)
at com.myApplication.Show.afterUpdate(Show.groovy:161)
at org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener.onApplicationEvent(AbstractPersistenceEventListener.java:46)
at Script1.run(Script1.groovy:17)
at org.grails.plugins.console.ConsoleService.eval(ConsoleService.groovy:57)
at org.grails.plugins.console.ConsoleService.eval(ConsoleService.groovy:37)
at org.grails.plugins.console.ConsoleController$_closure2.doCall(ConsoleController.groovy:61)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:198)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.myApplication.Show#1111]
... 12 more
Да, обычно функциональность базы данных зависит от базы данных для ее реализации. Вы, должно быть, делали это неправильно - H2 поддерживает блокировку и даже поддерживает MVCC. Включите ведение журнала SQL и выполните что-то вроде 'Show.lock (1111) ', и вы увидите SQL, похожий на' select ... from ... where ... for update', причем 'for update' является ключевой частью. Обратите внимание, что блокировка имеет смысл только в транзакции, поскольку это временной интервал, в течение которого блокировка должна быть активной, а диспетчер транзакций освобождает блокировку при совершении или откате. –
Да, я видел эту блокировку mysql для обновления в журналах запросов в спящем режиме. Но не знаю, почему это оптимистичное исключение блокировки. – Lovin