2012-05-02 9 views
5

Uso grails 2.0.0. Tengo tres objetos Miembro, Producto y Tipo de Producto. El miembro tiene muchos productos y es una relación de uno a muchos. El producto apunta a ProductType (tabla de referencia) y es una relación muchos a uno. Mi pregunta es sobre eliminar productos. Funciona en un escenario y no en otro. Sigue leyendo.Grails one-many mapping stalestaleexception en la clave compuesta

esbozo de las asignaciones siguientes:

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:

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

me dieron el código de servicio al cliente un esbozo de lo que es ...

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

Hasta aquí todo bien. Esto está funcionando perfectamente. Sin embargo, cuando me presento clave principal compuesta de la tabla T_PRODUCT de la siguiente manera:

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

me sale esto:

org.hibernate.StaleStateException: actualización por lotes por lotes UPDA volvió inesperado número de filas de actualización [0]; recuento de filas real: 0; esperado: 1 org.hibernate.StaleStateException: Actualización por lotes inesperada recuento de filas de la actualización [0]; recuento de filas real: 0; esperado: 1 en ProductService.cleanUpGorm (ProductService.groovy: 442) en ProductService.maintainProduct (ProductService.groovy: 213) en ClientService $ _maintainMembers_closure5.doCall (ClientService.groovy: 158) en ClientService.maintainMembers (ClientService.groovy : 152) en ClientService.processMembers (ClientService.groovy: 394)

Cualquier idea de dónde podría ir mal?

+0

¿No quiere decir static belongsTo = [member: Member] en lugar de static belongsTo = [member: Product]? – loteq

+0

Fue un error tipográfico. lo corrigió. Gracias. – arrehman

+0

¿Es posible proporcionar un caso de prueba? –

Respuesta

1

Recomiendo leer el Grails doc, 5.5.2.5 Composite Primary Keys. Ellos señalan lo siguiente, que no se ha respetado: clases

  1. dominio mapeados con claves primarias compuestas deben implementar la interfaz Serializable y anular los métodos equals() y hashCode(), utilizando las propiedades de la clave compuesta para los cálculos.
  2. También debe tener en cuenta que el uso de claves primarias compuestas es asociaciones, especialmente los nombres de las columnas asignadas.
  3. Puede ser, no es tan bueno usar un tipo mapeado muchos a uno en una clave compuesta.

Tal vez lo ayude a obtener la dirección correcta.

6

Su clase de dominio del producto debe implementar Serializable y reemplazar los métodos hashCode() y equals(), esto debe hacerse en situaciones donde utilice la clave compuesta.

su dominio de clase del producto debe ser así

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

    } 

Creo que de esta manera todo va a estar bien.

En caso de problemas, escriba.

+0

El dominio implementa Seriealizable, no lo pegó por simplicidad. Los métodos equals y hashCode también están en su lugar. Incluso con todo esto, no funciona. Tan pronto como vuelva a utilizar una clave primaria no compuesta para la clase de producto, funciona ... – arrehman

Cuestiones relacionadas