Quantcast

How do you specify an optional one-to-one with multiple owners

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

How do you specify an optional one-to-one with multiple owners

bjfish
With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


| Failure:  testSomething(optionalonetoone.CountryTests) 
|  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not insert: [optionalonetoone.Capitol]; uncategorized SQLException for SQL [insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?)]; SQL state [90006]; error code [90006]; NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147]; nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at optionalonetoone.CountryTests.testSomething(CountryTests.groovy:20) 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do you specify an optional one-to-one with multiple owners

Eric Ettes
If I understand correctly, you want to be able to create a capitol with [a state/a country/both/none], and a country or a state where you need to fill in the capitol? How about this construction; you'll make the capitol a leading entity to which either the country or state belong to, creating an optional one to one relation. 

(Please ignore this if I misunderstood you ;-))

class Capitol {

    static hasOne = [state: State, country: Country]

    static constraints = {
        state nullable: true
        country nullable: true
    }
}

class Country {

    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

class State {

    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

Kind regards,

-- 
Eric Ettes
Sent with Sparrow

On Wednesday, May 2, 2012 at 5:33 PM, Brandon Fish wrote:

With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


| Failure:  testSomething(optionalonetoone.CountryTests) 
|  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not insert: [optionalonetoone.Capitol]; uncategorized SQLException for SQL [insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?)]; SQL state [90006]; error code [90006]; NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147]; nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at optionalonetoone.CountryTests.testSomething(CountryTests.groovy:20) 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do you specify an optional one-to-one with multiple owners

ideasculptor
In reply to this post by bjfish


On Wed, May 2, 2012 at 8:33 AM, Brandon Fish <[hidden email]> wrote:
With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


You are looking for the 'mappedBy' directive.  Example and details here: http://grails.org/doc/latest/ref/Domain%20Classes/mappedBy.html

 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: How do you specify an optional one-to-one with multiple owners

Christian Rommel
In reply to this post by bjfish
Hey, 

regarding your subject, one-to-one does not go along with multiple owners. Also i would not use hasOne with nullable: true on the corresponding domain. Here is how you can setup your domains. 

If you like, you can delete in State domain hasOne Capitol and add Capitol capitol. In Capitol domain you can then add belongsTo State and make in both domains nullable true. Sure there is different setup with Capitol / Country mapping, but i would do it over the State, because this is the natural way.    



class Country {
    
    static hasMany = [states: State]
    
    static constraints = { 
    } 
}

class State {

    static belongsTo = [country: Country]
    static hasOne = [capital: Capitol]
    
    static constraints = { 
    } 
}

class Capitol {

    State state

    static constraints = { 

    } 
}


Date: Wed, 2 May 2012 10:33:37 -0500
From: [hidden email]
To: [hidden email]
Subject: [grails-user] How do you specify an optional one-to-one with multiple owners

With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


| Failure:  testSomething(optionalonetoone.CountryTests) 
|  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not insert: [optionalonetoone.Capitol]; uncategorized SQLException for SQL [insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?)]; SQL state [90006]; error code [90006]; NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147]; nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at optionalonetoone.CountryTests.testSomething(CountryTests.groovy:20) 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do you specify an optional one-to-one with multiple owners

bjfish
To clarify, I plan for the Capitol to have one of either the State or Capitol at a time.

I believe the entity diagram would look like the following with either the state or country being the owner:
State 0..1 ----- 1  Capitol  1 ----  0..1 Country

There would be only one owner at a time.  Given the responses I'm still not sure how to model this.

On Wed, May 2, 2012 at 11:17 AM, Christian Rommel <[hidden email]> wrote:
Hey, 

regarding your subject, one-to-one does not go along with multiple owners. Also i would not use hasOne with nullable: true on the corresponding domain. Here is how you can setup your domains. 

If you like, you can delete in State domain hasOne Capitol and add Capitol capitol. In Capitol domain you can then add belongsTo State and make in both domains nullable true. Sure there is different setup with Capitol / Country mapping, but i would do it over the State, because this is the natural way.    



class Country {
    
    static hasMany = [states: State]
    
    static constraints = { 
    } 
}

class State {

    static belongsTo = [country: Country]
    static hasOne = [capital: Capitol]
    
    static constraints = { 
    } 
}

class Capitol {

    State state

    static constraints = { 

    } 
}


Date: Wed, 2 May 2012 10:33:37 -0500
From: [hidden email]
To: [hidden email]
Subject: [grails-user] How do you specify an optional one-to-one with multiple owners


With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


| Failure:  testSomething(optionalonetoone.CountryTests) 
|  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not insert: [optionalonetoone.Capitol]; uncategorized SQLException for SQL [insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?)]; SQL state [90006]; error code [90006]; NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147]; nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at optionalonetoone.CountryTests.testSomething(CountryTests.groovy:20) 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do you specify an optional one-to-one with multiple owners

Eric Ettes
How about this construction; both Country and State are a Governed Entity, and Capitol has one of those. 

You can use capitol.governedEntity.instanceOf(Country) to determine wether that governedEntity is a Country or not, and Capitol will always have one of either (or none):

class Country extends GovernedEntity {
    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

class State extends GovernedEntity {
    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

class Capitol {
    static hasOne = [governedEntity: GovernedEntity]
    static constraints = {
        governedEntity nullable: true
    }
}

-- 
Eric Ettes
Sent with Sparrow

On Wednesday, May 2, 2012 at 6:28 PM, Brandon Fish wrote:

To clarify, I plan for the Capitol to have one of either the State or Capitol at a time.

I believe the entity diagram would look like the following with either the state or country being the owner:
State 0..1 ----- 1  Capitol  1 ----  0..1 Country

There would be only one owner at a time.  Given the responses I'm still not sure how to model this.

On Wed, May 2, 2012 at 11:17 AM, Christian Rommel <[hidden email]> wrote:
Hey, 

regarding your subject, one-to-one does not go along with multiple owners. Also i would not use hasOne with nullable: true on the corresponding domain. Here is how you can setup your domains. 

If you like, you can delete in State domain hasOne Capitol and add Capitol capitol. In Capitol domain you can then add belongsTo State and make in both domains nullable true. Sure there is different setup with Capitol / Country mapping, but i would do it over the State, because this is the natural way.    



class Country {
    
    static hasMany = [states: State]
    
    static constraints = { 
    } 
}

class State {

    static belongsTo = [country: Country]
    static hasOne = [capital: Capitol]
    
    static constraints = { 
    } 
}

class Capitol {

    State state

    static constraints = { 

    } 
}


Date: Wed, 2 May 2012 10:33:37 -0500
From: [hidden email]
To: [hidden email]
Subject: [grails-user] How do you specify an optional one-to-one with multiple owners


With the example classes below, I tried to model an optional one-to-one (zero or one) with State and Country both being optional owners of Capitol but this fails with the following error. How should a zero or one relationship be specified where the child has more than one owner?

package optionalonetoone 


class Capitol { 

    State state 
    Country country 
    static constraints = { 
        state(nullable:true) 
        country(nullable:true) 
    } 


package optionalonetoone 

class Country { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


package optionalonetoone 

class State { 
    static hasOne = [capitol:Capitol] 
    static constraints = { 
    } 


    @Test 
    void testSomething() { 
        assert new Country(capitol:new Capitol()).save(failOnError:true) 
    }


| Failure:  testSomething(optionalonetoone.CountryTests) 
|  org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not insert: [optionalonetoone.Capitol]; uncategorized SQLException for SQL [insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?)]; SQL state [90006]; error code [90006]; NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147]; nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at optionalonetoone.CountryTests.testSomething(CountryTests.groovy:20) 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "STATE_ID"; SQL statement: 
insert into capitol (id, version, country_id, state_id) values (null, ?, ?, ?) [90006-147] 
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:327) 


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How do you specify an optional one-to-one with multiple owners

ideasculptor


On Wed, May 2, 2012 at 9:43 AM, Eric Ettes <[hidden email]> wrote:
How about this construction; both Country and State are a Governed Entity, and Capitol has one of those. 

You can use capitol.governedEntity.instanceOf(Country) to determine wether that governedEntity is a Country or not, and Capitol will always have one of either (or none):

class Country extends GovernedEntity {
    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

class State extends GovernedEntity {
    static belongsTo = [capitol: Capitol]
    static constraints = {
        capitol nullable: false
    }
}

class Capitol {
    static hasOne = [governedEntity: GovernedEntity]
    static constraints = {
        governedEntity nullable: true
    }
}


Wouldn't you put the capitol property in GovernedEntity if you were going to do it via a common base class - which is probably the appropriate way to do it if you want it to have EITHER a state OR a country rather than the potential for both, since your domain model would then be correctly enforcing your logical construction.  You could have two properties in capitol and only assign to one of them at a time, but then you've got to enforce that constraint or risk having an entity in an inconsistent state.  And for the record, a 'capitol' is a building that houses a legislative assembly, and a 'capital' is a city that is the seat of govt.

Loading...