Reputation: 1322
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?
Upvotes: 5
Views: 1460
Reputation: 1075
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.
Upvotes: 6
Reputation: 2820
I strongly recommend reading the Grails doc, 5.5.2.5 Composite Primary Keys. They do point out the following, which you did not respect:
Serializable
interface and override the equals()
and hashCode()
methods, using the properties in the composite key for the calculations.Maybe it help you getting the right direction.
Upvotes: 1