5

我使用 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"
   }
}

产品.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)

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

4

2 回答 2

6

Your Product domain class must implements Serializable and override methods hashCode() and equals(), this thing must be done in situations where you use composite key.

Your Product domain class must be like this

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

    }

I think this way everything will be OK.

In case of problems write.

于 2012-05-09T12:12:29.683 回答
1

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

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

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

于 2012-05-08T17:16:00.987 回答