Roland
Roland

Reputation: 487

grails gorm null fields

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

Answers (2)

Dónal
Dónal

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

Roland
Roland

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

Related Questions