I have one-to-many relationship between entities - RentalUnit and Review . All tests run fine, except when i am adding the same review to different RentalUnit instances as following:
def review3 = Review.build().save(flush: true)
def rentalUnit2 = RentalUnit.build().
addToReviews(review2).addToReviews(review3).save(flush: true)
assert rentalUnit.reviews.contains(review2)
It seems that GORM and the addTo*
method doesn't seem to care if i am adding the same Review instance, so i am guessing there is something missing in my domain classes. What would that be?
Thank you for helping
p.s.
class Review {
String submittedBy
String content
String dateReceived
boolean isApproved
static belongsTo = RentalUnit
static mapping = {
content type: 'text'
}
static constraints = {
submittedBy blank: false, size: 3..50
content blank: false, size: 5..2500
}
}
class RentalUnit {
String name
String nickname
Address address
static hasMany = [reviews:Review]
static mapping = {
reviews cascade: "all-delete-orphan"
}
static constraints = {
name blank: false, unique: true, size: 4..10
nickname blank: false, size: 5..60
}
}
Yes it doesn't care - it doesn't change any other objects' properties. Even about the other end of relationship - review2.rentalUnit
(if such field existed) will be null here.
The Review will disappear from rentalUnit.reviews
(or review2.rentalUnit
would be assigned) the next time the object is loaded from database.
You can assign review2.rentalUnit
by hand and validate if it's been added to another RentalUnit
, though - the assignment will do no harm.
edit: let's go through the code step-by-step.
rentalUnit1.addToReviews(review2)
Here review2
is added to rentalUnit1.reviews
. review2.rentalUnit
is NOT assigned, but after save in the database it would point to rentalUnit1
. The only persistent representation of RentalUnit.reviews
field is a child-to-parent reference field, Review.rentalUnit
.
def rentalUnit2 = ...
rentalUnit2.addToReviews(review2).addToReviews(review3).save(flush: true)
Here review2
is added to rentalUnit2.reviews
. review2.rentalUnit
is NOT assigned again. review2
is NOT removed from rentalUnit1.reviews
BUT, after save, in the database, it will point to rentalUnit2
.
assert rentalUnit1.reviews.contains(review2)
review2
was NOT removed from rentalUnit1.reviews
, so the assertion will pass. BUT in the next session rentalUnit1
and rentalUnit2
will have the correct sets of review
s - only rentalUnit2
will have review2
.
Now, if you want to always maintain Java representation consistent, implment a method like this:
class RentalUnit {
RentalUnit addToReviewsAndCheck(Review r) {
if (r.rentalUnit == this) return;
if (r.rentalUnit != null) {
r.rentalUnit.removeFromReviews(r)
}
r.rentalUnit = this
addToReviews(r)
}
}
but it's an overkill, as for me.