Hibernate Grails复合键上的一对多映射异常

Hibernate Grails复合键上的一对多映射异常,hibernate,grails,gorm,Hibernate,Grails,Gorm,我使用Grails2.0.0。我有三个对象:成员、产品和产品类型。会员拥有多种产品,是一对多关系。Product指向ProductType(参考表),是一个多对一关系。我的问题是关于删除产品。它在一个场景中有效,而在另一个场景中无效。继续读下去 以下是映射的大致轮廓: Member.groovy: Product.groovy: ProductType.groovy: 我得到了客户服务代码,其概要是 if((newMember.products) && (newMembe

我使用Grails2.0.0。我有三个对象:成员、产品和产品类型。会员拥有多种产品,是一对多关系。Product指向ProductType(参考表),是一个多对一关系。我的问题是关于删除产品。它在一个场景中有效,而在另一个场景中无效。继续读下去

以下是映射的大致轮廓:

Member.groovy:

Product.groovy:

ProductType.groovy:

我得到了客户服务代码,其概要是

    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:返回批upda批更新 来自更新[0]的意外行计数;实际行数:0;预期:1 org.hibernate.StaleStateException:批处理更新返回了意外结果 来自更新的行计数[0];实际行数:0;预计:1分 ProductService.cleanUpGorm(ProductService.groovy:442)位于 ProductService.maintainProduct(ProductService.groovy:213)位于 ClientService$\u maintainemembers\u closure5.doCall(ClientService.groovy:158) 在ClientService.maintainemembers(ClientService.groovy:152)处 processMembers(ClientService.groovy:394)


你知道我哪里出了问题吗?

我强烈建议你阅读这本书。他们确实指出了你不尊重的以下几点:

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

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

    您的产品域类必须实现可序列化的
    并重写方法
    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()
            }
    
        }
    
    我想这样一切都会好起来的


    如果出现问题,请写。

    你是说静态belongsTo=[member:member]而不是静态belongsTo=[member:Product]?这是一个打字错误。更正了。谢谢。有可能提供一个测试用例吗?域确实实现了Seriealizable,但为了简单起见没有粘贴它。equals和hashCode方法也已就位。即使如此,它也不起作用。一旦我切换回使用产品类的非复合主键,它就会工作。。。
        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)
            }
        }
    
       static mapping = {
            table 'T_PRODUCT'
            //id column:'PRODUCT_ID'
            id composite:['member', 'productType']
            member column: 'MEMBER_ID'
            productType column: 'PRODUCT_TYPE'
            ...
       }
    
    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()
            }
    
        }