【问题标题】:Grails one-many mapping stalestaleexception on composite key复合键上的 Grails 一对多映射 stalestaleexception
【发布时间】:2012-05-12 11:20:06
【问题描述】:

我使用 grails 2.0.0。我有三个对象 Member、Product 和 ProductType。成员有许多产品,并且是一对多的关系。 Product 指向 ProductType(参考表)并且是多对一的关系。我的问题是关于删除产品。它适用于一种情况,而不适用于另一种情况。继续阅读。

以下映射的大致轮廓:

会员.groovy:

class Member  {
   Long id
   ....
   SortedSet products
   static hasMany = [products:Product]
   static mapping = {
        table 'T_MEMBER'
        id column:'MEMBER_ID'...
       products cascade: "all-delete-orphan"
   }
}

Product.groovy:

class Product {
   Long id
   ProductType productType
   ...
   static belongsTo = [member:Member]
   static mapping = {
        table 'T_PRODUCT'
        id column:'PRODUCT_ID'
        member column: 'MEMBER_ID'
        productType column: 'PRODUCT_TYPE'
        ...
   }
}

ProductType.groovy:

class ProductType {
   Long id
   ..
   static mapping = {
        table 'T_PRODUCT_TYPE'
        id column:'PRODUCT_TYPE', generator:'assigned'
    ...
   }
}

我得到了客户服务代码,其大纲是...

    if((newMember.products) && (newMember.products.size() >0)) {
        def addList = newMember.products - existingMember.products
        def removeList = existingMember.products- newMember.products
        removeList.each { product ->
            existingMember.removeFromProducts(product)
        }
        addList.each {product ->
            existingMember.addToProducts(product)
        }
    }

到目前为止一切顺利。这是完美的工作。但是,当我通过执行以下操作为 T_PRODUCT 表引入复合主键时:

   static mapping = {
        table 'T_PRODUCT'
        //id column:'PRODUCT_ID'
        id composite:['member', 'productType']
        member column: 'MEMBER_ID'
        productType column: 'PRODUCT_TYPE'
        ...
   }

我明白了:

org.hibernate.StaleStateException:批量更新返回批量更新 来自更新 [0] 的意外行数;实际行数:0;预期:1 org.hibernate.StaleStateException:批量更新返回意外 来自更新 [0] 的行数;实际行数:0;预期:1 在 ProductService.cleanUpGorm(ProductService.groovy:442) 在 ProductService.maintainProduct(ProductService.groovy:213) 在 ClientService$_maintainMembers_closure5.doCall(ClientService.groovy:158) 在 ClientService.maintainMembers(ClientService.groovy:152) 在 ClientService.processMembers(ClientService.groovy:394)

知道我哪里可能出错了吗?

【问题讨论】:

  • 你的意思不是静态的 belongsTo = [member:Member] 而不是静态的 belongsTo = [member:Product] 吗?
  • 这是一个错字。纠正它。谢谢。
  • 可以提供测试用例吗?

标签: hibernate grails grails-orm


【解决方案1】:

您的 Product 域类必须实现 Serializable 并覆盖方法 hashCode()equals(),这必须在您使用复合键的情况下完成。

您的 Product 域类必须是这样的

class Product implements Serializable {
        Long id
        ProductType productType
        ...

        static mapping = {
             table 'T_PRODUCT'
             id composite:['member', 'productType']
             member column: 'MEMBER_ID'
             productType column: 'PRODUCT_TYPE'
        }

        boolean equals(other) {
            if (!(other instanceof Product )) {
                return false
            }
            other.member== member && other.productType== productType
        }

        int hashCode() {
            def builder = new HashCodeBuilder()
            builder.append member
            builder.append productType
            builder.toHashCode()
        }

    }

我认为这样一切都会好起来的。

万一出现问题写。

【讨论】:

  • 该域确实实现了Seriealizable,为简单起见没有粘贴它。 equals 和 hashCode 方法也已经到位。即使有这一切,它也不起作用。一旦我切换回使用 Product 类的非复合主键,它就可以工作......
【解决方案2】:

我强烈推荐阅读Grails doc, 5.5.2.5 Composite Primary Keys。他们确实指出了您不尊重的以下内容:

  1. 使用复合主键映射的域类必须实现Serializable 接口并覆盖equals()hashCode() 方法,使用复合键中的属性进行计算。
  2. 您还需要注意使用复合主键是关联,尤其是映射的列名。
  3. 可能是,在复合键中使用多对一映射类型并不是很好。

也许它可以帮助您找到正确的方向。

【讨论】:

    猜你喜欢
    • 2015-07-18
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多