2012-05-02 8 views
5

私はgrails 2.0.0を使用します。 Member、Product、ProductTypeの3つのオブジェクトがあります。メンバーには多くの商品があり、1対多の関係です。製品はProductType(参照表)を指し、多対1の関係です。私の質問は、製品を削除することです。あるシナリオでは動作し、別のシナリオでは動作しません。読む。Grails one-manyマッピング複合キーのstalestaleexception

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

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:

0以下のマッピングの

ラフアウトライン

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

...とても良いです概要そのクライアントサービスのコードを得ました。これは完全に機能しています。

org.hibernate.StaleStateException:

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

私はこの取得:私は、次の手順でT_PRODUCTテーブルの複合主キーを導入する場合しかしながら、バッチUPDAバッチ更新は、更新から 予想外の行数を返しました[0];実際の行数:0;予期される:1 org.hibernate.StaleStateException:バッチ更新が予期せず返されました。 update [0]からの行数。実際の行数:0;予想: ProductService.maintainProduct(ProductService.groovy:213):1 ProductService.cleanUpGorm(442 ProductService.groovy)で:ClientService.maintainMembersで (ClientService.groovy ClientService $ _maintainMembers_closure5.doCall(158 ClientService.groovy)で:152)at ClientService.processMembers(ClientService.groovy:394)

どこが間違っているのでしょうか?

+0

あなたはstatic belongsTo = [member:Product]の代わりに の代わりにstatic belongsTo = [member:Member]を使用しますか? – loteq

+0

それはタイプミスでした。それを訂正した。ありがとう。 – arrehman

+0

テストケースを提供することは可能ですか? –

答えて

1

Grails doc, 5.5.2.5 Composite Primary Keysを読むことを強くお勧めします。彼らはあなたが尊重しなかった、次のように指摘します:複合主キーにマッピングされ

  1. ドメインクラスは、計算のための複合キーのプロパティを使用して、Serializableインタフェースを実装し、equals()hashCode()メソッドをオーバーライドする必要があります。
  2. また、コンポジット主キー、特にマッピングされた列名を使用することに注意する必要があります。
  3. 複合キーに多対1のマップ型を使用するのは良いことではありません。

おそらく正しい方向を得るのに役立ちます。

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

    } 

ようにする必要があり

私はこの方法のすべてがOKになると思います。

問題が発生した場合。

+0

ドメインはSeriealizableを実装していますが、簡単に貼り付けることはできません。 equalsメソッドとhashCodeメソッドも実装されています。このすべてでさえ、うまくいきません。 Productクラスの非複合プライマリキーを使用するように切り替えるとすぐに動作します... – arrehman