Grails one-many映射复合键上的stalestaleexception

arr*_*man 5 grails hibernate grails-orm

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

下面的映射的粗略轮廓:

Member.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"
   }
}
Run Code Online (Sandbox Code Playgroud)

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'
        ...
   }
}
Run Code Online (Sandbox Code Playgroud)

ProductType.groovy:

class ProductType {
   Long id
   ..
   static mapping = {
        table 'T_PRODUCT_TYPE'
        id column:'PRODUCT_TYPE', generator:'assigned'
    ...
   }
}
Run Code Online (Sandbox Code Playgroud)

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

    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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.这很完美.但是,当我通过执行以下操作为T_PRODUCT表引入复合主键时:

   static mapping = {
        table 'T_PRODUCT'
        //id column:'PRODUCT_ID'
        id composite:['member', 'productType']
        member column: 'MEMBER_ID'
        productType column: 'PRODUCT_TYPE'
        ...
   }
Run Code Online (Sandbox Code Playgroud)

我明白了:

org.hibernate.StaleStateException:批量更新批量更新从update [0]返回意外行数; 实际行数:0; expected:1 org.hibernate.StaleStateException:批量更新从update [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)at ClientService.processMembers(ClientService.groovy:394)

知道我可能会出错吗?

Kar*_*ren 6

您的Product域类必须实现Serializable和覆盖方法,hashCode()并且equals()必须在使用组合键的情况下完成此操作.

您的产品域类必须是这样的

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()
        }

    }
Run Code Online (Sandbox Code Playgroud)

我想这样一切都会好的.

如果有问题写.


mic*_*fra 1

我强烈建议阅读Grails 文档 5.5.2.5 复合主键。他们确实指出了您不尊重的以下几点:

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

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