Grails

unable to create both a 1:1 and a 1:Many between two classes if 'many' side belongsTo the 'one' side

Details

  • Type: Sub-task Sub-task
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Won't Fix
  • Affects Version/s: 1.0.3
  • Fix Version/s: None
  • Component/s: Persistence
  • Labels:
    None
  • Environment:
    Windows XP, JDK 1.6.0_06
  • Testcase included:
    yes

Description

I'm unable to create instances of domain classes if they have both a 1:1 and a 1:Many relationship where the 'many' side belongsTo the 'one' side. Here is what I wanted to define the classes:

class User {
String name
Address billingAddress
static hasMany = [businessLocations : Address]
}
class Address {
String street
static belongsTo=[user: User]
}

I attempted to create instances of the User class with this code:

def user = new User(name: 'foo',billingAddress: new Address(street: 'billing')).save(flush:true)

but this results in an exception:

errors.GrailsExceptionResolver org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: AddressBoth.user; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: AddressBoth.user
org.codehaus.groovy.runtime.InvokerInvocationException: org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: AddressBoth.user; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: AddressBoth.user

The attached test application has several variations on the User/Address classes that implement either just a 1:1 relationship, 1:Many relationship, and both 'self managed' 1:1 & 1:Many relationships. These classes have brief integration tests that pass.

The failing classes are named UserBoth.groovy and AddressBoth.groovy and have a failing integration test in AddressBothTests.groovy.

The work around for this issue is to self-manage the relationships.

Activity

Hide
Ryan Fioravanti added a comment -

I am experiencing this problem as well. Mine is just a 1 to many relationship, not both. I get the error when an object from the many tries to refer back to what it belongs to.

Example:

BlogPost has many Comments

Comment is associated with a commenter (User)

BlogPost belongs to User
Comment belongs to BlogPost

When I have a comment object and try to refer to the BlogPost it belongs to I get the exception mentioned previously

Show
Ryan Fioravanti added a comment - I am experiencing this problem as well. Mine is just a 1 to many relationship, not both. I get the error when an object from the many tries to refer back to what it belongs to. Example: BlogPost has many Comments Comment is associated with a commenter (User) BlogPost belongs to User Comment belongs to BlogPost When I have a comment object and try to refer to the BlogPost it belongs to I get the exception mentioned previously
Hide
Graeme Rocher added a comment -

There is no scope / time to resolve these remaining lower priority issues for 1.2 so moving to 1.3

for 1.2 final only issues considered blocking will now be fixed

Show
Graeme Rocher added a comment - There is no scope / time to resolve these remaining lower priority issues for 1.2 so moving to 1.3 for 1.2 final only issues considered blocking will now be fixed
Hide
Victor Sergienko added a comment -

Same mysterious thing here, on 1.3.5 on a String property.
Happens in an explicit transaction, when assigning a.properties = params. Probably some undesirable flush() happens at that moment.

Show
Victor Sergienko added a comment - Same mysterious thing here, on 1.3.5 on a String property. Happens in an explicit transaction, when assigning a.properties = params. Probably some undesirable flush() happens at that moment.
Hide
Graeme Rocher added a comment -

The solution for this now is to use a hasOne:

@Entity
class UserBoth {
    String name
    static hasOne = [billingAddress:AddressBoth ]
    static hasMany = [businessLocations : AddressBoth]
    static mappedBy = [billingAddress:'user']
}
Show
Graeme Rocher added a comment - The solution for this now is to use a hasOne:
@Entity
class UserBoth {
    String name
    static hasOne = [billingAddress:AddressBoth ]
    static hasMany = [businessLocations : AddressBoth]
    static mappedBy = [billingAddress:'user']
}

People

Vote (15)
Watch (10)

Dates

  • Created:
    Updated:
    Resolved: