【问题标题】:grails/hibernate: add pessimistic locking on using creteriagrails/hibernate:在使用条件时添加悲观锁定
【发布时间】:2014-11-19 11:28:05
【问题描述】:

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

"ERROR 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"
                    }
                }
            }
        }

【问题讨论】:

  • 您使用的是哪个数据库?
  • 我正在使用休眠数据库
  • Hibernate 只是您的应用程序和底层数据库之间的一层。该数据库可以是 H2(Grails 提供的 in-mem 数据库)、PostgreSQL、SQL Server、Oracle、MySql ......你能列出你的DataSource.groovy 文件的内容吗(一定要删除任何私人信息,如 IP 和密码,但是)?
  • 我编辑了我的问题
  • 谢谢您,您使用的是H2数据库,但我想我现在明白问题所在了。将发布正确的答案。

标签: hibernate grails groovy pessimistic-locking


【解决方案1】:

根据您形成查询的方式,Hibernate 将执行不同的查询。编写查询的方式 Hibernate 将执行连接 - 这可能对性能有好处,因为这意味着您的连接实体已经在 1 查询中被预取。然而,对于锁定来说,这是不好的,因为每个连接的表都必须被锁定,这会对深层层次结构产生相当大的影响。因此,您的数据库不允许这样做(我什至不确定是否有其他数据库允许)。

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

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

【讨论】:

  • 我没有使用statis方法belongsTo,所以不能直接从child获取parent对吧?
  • 我添加了域类
  • 您可以将static belongsTo = [parent:Parent] 添加到您的Child 类中,并通过child.parent(然后您将使用lock())或Parent.lock(child.parent.id)(请参阅我链接的文章中有两个,但后面的形式可能更好)。您应该知道,这将更改 GORM 生成的架构 - 使用您当前的设置,它会创建一个映射表(可能称为 parent_child),并且使用修改后的设置,它只会在 child 中包含一个 parent_id 列代替表。
  • 当你对父类返回的实例执行加锁时,子类是否也被加锁?
  • 不,子对象未锁定。但是如果你总是先锁定父母,那么孩子可能是安全的,只要他们只有 1 个父母并且其他应用程序没有与数据库交互。但请不要 100% 相信我,先尝试测试它。
猜你喜欢
  • 2014-08-30
  • 1970-01-01
  • 1970-01-01
  • 2018-10-22
  • 2015-03-24
  • 2013-09-16
  • 2015-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多