Let's say I have a grails domain class that looks like
class Person {
Address address
}
I could also declare it as
class Person {
static hasOne = [address:Address]
}
The second way would move the foreign key to the Address table rather than the person table.
What are the practical benefits (or disadvantages) of doing this one way vs the other? As far as I understand, they will both use foreign keys, it's just a matter of where the foreign key lives.
If the foreign key exists on the address table, then that address can only have one person.
If the foreign key is on the person table, multiple persons can have the same address.
It's not about what way is better/worse. It's about what is the correct way to model your data.
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.
I suggest the following...
class Person {
...
static hasOne = [address: Address]
}
class Address {
...
static belongsTo = [person: Person]
}
A person has one address and the address belongs to one person.
By this way, when you delete a person, the address will be deleted too, without problems.
I think this is the better way to do this.
The Person "hasOne" Address and the Address "belongsTo" the Person.
Having the foreign key on the "child" table makes more sense because this way the child would break if the parent is missing. A Person can exist without its address but a "person's address" without a person makes no sense. So the Address should be the weaker side of the relationship.
Doing it this way in grails both entities will have the reference to each other so it won't feel weird. Also the default cascading behaviour will save and delete the Address when you save the Person but if you want to delete the Address the Person will remain saved.