grails / hibernate:使用条件添加悲观锁定

时间:2014-11-19 11:28:05

标签: hibernate grails groovy pessimistic-locking

我试图在我的creteria中添加悲观锁定,如文档中所示 http://grails.org/doc/latest/guide/GORM.html#locking但我有一个例外:

" ERROR util.JDBCExceptionReporter - 功能不受支持:" FOR UPDATE&& JOIN&#34 ;; 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 个答案:

答案 0 :(得分:3)

根据您构建查询的方式,Hibernate将执行不同的查询。编写查询的方式Hibernate将执行连接 - 这可能对性能有利,因为这意味着已经在1查询中预先获取了已连接的实体。但是对于锁定而言这很糟糕,因为每个连接的表都必须被锁定,这对深度层次结构会产生很大的影响。因此,您的数据库不允许它(我甚至不确定是否有其他人)。

您必须在不加入的情况下执行查询。根据您的域类实现,可以在不触及数据库的情况下完成简单的Child.parent.id,然后您的查询变为简单的Parent.lock(Child.parent.id)。没有看到实际的域类,很难说。

您可以随时执行的操作是在非锁定查询中获取Parent,然后在返回的实例上调用lock()方法。我建议你看看这个关于GORM锁定事物的优秀article以获取更多信息。