Grails one-many mapping stalestaleexception on composite key
grails, grails-orm, hibernate
Solution
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.
Problem
I use grails 2.0.0. I have three objects Member, Product and ProductType. Member has many Products and is a one-to-many relation. Product points to ProductType (reference table) and is a many-to-one relation. My question is about deleting Products. It works in one scenario and not in another. Read on. Rough outline of the mappings below: 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' ... } } ``` I got the client service code an outline of which is ... ``` 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) } } ``` So far so good. This is working perfectly. However when I introduce composite primary key for the T_PRODUCT table by doing the following: ``` static mapping = { table 'T_PRODUCT' //id column:'PRODUCT_ID' id composite:['member', 'productType'] member column: 'MEMBER_ID' productType column: 'PRODUCT_TYPE' ... } ``` I get this: org.hibernate.StaleStateException: Batch upda Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 at ProductService.cleanUpGorm(ProductService.groovy:442) at ProductService.maintainProduct(ProductService.groovy:213) at ClientService$_maintainMembers_closure5.doCall(ClientService.groovy:158) at ClientService.maintainMembers(ClientService.groovy:152) at ClientService.processMembers(ClientService.groovy:394) Any idea where I might be going wrong?