grails hasOne vs direct member variable

前端 未结 4 946
余生分开走
余生分开走 2021-02-04 02:10

Let\'s say I have a grails domain class that looks like

class Person {
    Address address
}

I could also declare it as

class P         


        
4条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-02-04 02:44

    I find the use of hasOne in Grails to be particularly confusing. For example, this question asks what happens when a toOne relationship is declared as follows:

    class Person {
      static hasOne = [address: Address]
    }
    

    As stated above, this causes the person_id foreign key to appear in the Address table, which means that each Address can only point at one Person. What I find bizarre, then, is that even though the code is written as "a Person has one Address", the actual result is that "an Address has one Person".

    And in fact, defined solely as above, there's nothing (at the database level) preventing more than one Address record from pointing at the same Person, which means that a Person doesn't really have to have one Address after all.

    Interestingly, you'd get the same database representation if you created the Address class like this:

    class Address {
        Person person
    }
    

    The person_id foreign key will be in the Address table, just as like in the previous example, but obviously, you can't get from the Person to the Address in the code without defining that relationship in some way as well.

    Also interesting is that, if you were modeling a toMany relationship from Person to Address in the database, you'd use the same table layout. You'd put the parent's primary key (person_id) into the child table. From a database perspective then, using hasOne creates the same structure that a toMany relationship would create.

    Of course, we're not just creating database tables, we're creating Grails domain classes that have some behavior associated with them, and some enforcement of relationship semantics. In this particular business example, you probably don't want to share the same Address record with multiple People, you just want to store the Address separately (maybe preparing for the day when a Person has multiple Addresses). I'd probably vote for this approach:

    class Person {
        Address address
    
        static constraints = {
            address unique:true
        }
    }
    

    The address_id foreign key will be in the Person table, and the unique constraint will enforce that no two Person records are pointing at the same Address.

提交回复
热议问题