Grails/ Hibernate: добавить пессимистическую блокировку при использовании Creteria
Я попытался добавить пессимистическую блокировку в свой creteria, как показано в документе http://grails.org/doc/latest/guide/GORM.html но у меня было исключение:
"ОШИБКА util.JDBCExceptionReporter - функция не поддерживается: "FOR UPDATE && JOIN"; оператор SQL: ... org.hibernate.exception.GenericJDBCException: не удалось выполнить запрос"
Я пытался добавить блокировку в двух местах:
def ParentInstance = Parent.createCriteria().get {
Childs {
idEq(ChildInstance.id)
lock true
}
А также
def ParentInstance = Parent.createCriteria().get {
Childs {
idEq(ChildInstance.id)
}
lock true
}
Дополнительный вопрос: правильно ли использовать пессимистическую блокировку ассоциации?
Спасибо
Домен
class Parent{
static hasMany = [Childs:Child]
}
class Child{
}
DataSource.groovy
dataSource {
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
// environment specific settings
environments {
development {
dataSource {
dbCreate = "update" // one of 'create', 'create-drop', 'update', 'validate', ''
url = "jdbc:h2:myApp_prodDb;MVCC=TRUE"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:h2:mem:myApp_testDb;MVCC=TRUE"
}
}
production {
dataSource {
dbCreate = "update"
url = "jdbc:h2:myApp_prodDb;MVCC=TRUE"
pooled = true
properties {
maxActive = -1
minEvictableIdleTimeMillis=1800000
timeBetweenEvictionRunsMillis=1800000
numTestsPerEvictionRun=3
testOnBorrow=true
testWhileIdle=true
testOnReturn=true
validationQuery="SELECT 1"
}
}
}
}
1 ответ
В зависимости от того, как вы формируете запрос, Hibernate будет выполнять разные запросы. То, как написан ваш запрос, Hibernate выполнит соединение - это может быть полезно для производительности, потому что это означает, что ваши объединенные сущности уже будут предварительно извлечены в 1 запросе. Однако для блокировки это плохо, так как каждая объединенная таблица должна быть заблокирована, и это может оказать значительное влияние на глубокие иерархии. Таким образом, ваша база данных не позволяет этого (я даже не уверен, что любой другой делает).
Вы должны будете выполнить свой запрос без объединений. В зависимости от вашей реализации класса домена простой Child.parent.id
можно сделать, не касаясь базы данных, и тогда ваш запрос становится простым Parent.lock(Child.parent.id)
, Трудно сказать, не видя реальных классов домена.
Что вы всегда можете сделать, это получить Parent
в неблокирующем запросе, а затем вызвать lock()
метод на возвращенном экземпляре. Я бы посоветовал вам взглянуть на эту прекрасную статью о блокировке вещей в GORM для получения дополнительной информации.