Reputation: 487
I have a two domain classes:
class Person {
String lastname
String firstname
String alias
Date birthday
String notes
static belongsTo = [addressBook: AddressBook, mainAddress: Address]
static hasMany = [tags: Tag, addresses: Address]
static constraints = {
mainAddress nullable: true
addresses nullable: true
alias nullable: true
birthday: nullable: true
tags nullable: true
notes nullable: true
}
}
and
class Address {
AddressType addressType
static belongsTo = [person: Person]
String company
String street
String zipCode
String city
String eMail
String phone
String mobile
String website
static constraints = {
person nullable: true
company nullable: true
website nullable: true
}
}
It is intended, that every person has multiple addresses and can define one address as main-address.
Inside my controller I do a
params.max = Math.min(max ?: 10, 100)
respond Person.list(params)
to load all persons with all addresses. The person-objects I receive contain a addresses-list with all addresses and the mainAddress. But the addresses that are used as main address have only empty (null) fields in both objects (the one in the list and the mainAddress-object.). When I dont set the mainAddress the address-object in the addresses-list comes with all fields properly set. The database fields (I use the in-memory-db so far) seem to be correct:
create table address (id bigint generated by default as identity, version bigint not null, address_type varchar(255) not null, city varchar(255) not null, company varchar(255), e_mail varchar(255) not null, mobile varchar(255) not null, person_id bigint, phone varchar(255) not null, street varchar(255) not null, website varchar(255), zip_code varchar(255) not null, primary key (id))
create table person (id bigint generated by default as identity, version bigint not null, address_book_id bigint not null, alias varchar(255), birthday timestamp not null, firstname varchar(255) not null, lastname varchar(255) not null, main_address_id bigint, notes varchar(255), primary key (id))
Has anyone an idea, why my mapping is not working?
Thanks for your help in advance
Roland
Upvotes: 0
Views: 1974
Reputation: 187499
There are a number of things wrong with your model, the most serious is that the person-mainAddress relationship has no owner, i.e. each side belongsTo
the other. If possible, I would simplify your model to
class Person {
// non-address properties omitted, because they're not relevant to this question
static hasMany = [addresses: Address]
Address getMainAddress() {
Address.createCriteria().get {
eq 'person', this
eq 'isMain', true
}
}
static transients = ['mainAddress']
static constraints = {
addresses nullable: true, validator: { addresses ->
// this prevents a person from having more than one main address
addresses?.count { it.isMain } <= 1
}
}
}
class Address {
// non-person properties omitted, because they're not relevant to this question
boolean isMain = false
static belongsTo = [person: Person]
static constraints = {
// is it really OK for an address not to be associated with a person?
person nullable: true
}
}
I think this meets your requirements, but is a simpler model because there is only a single (one-to-many) relationship between Person
and Address
Upvotes: 1
Reputation: 487
I've now found a solution:
class Person {
Address mainAddress
static hasMany = [addresses: Address]
static constraints = {
addresses nullable: true
mainAddress nullable: true, unique: true
}
static mapping = {
addresses joinTable: [name: 'person_address',key: 'person_id', column: 'address_id']
mainAddress lazy: false
}
}
class Address {
}
This way the addresses are mapped over the join-table person_address, while the mainAddress is mapped via main_address_id in the address-table. The "mainAddress: lazy"-mapping is required, because otherwise the fields of the mainAddress are not populated.
Upvotes: 1