OrlandoL
OrlandoL

Reputation: 948

Grails belongsTo relationship fails on save due to null id

I'm having some trouble with my GORM relationship management. Basically there are 4 domain classes that are in the scope of this question. A House is a restaurant which has multiple Queue, each of which has multiple Ticket. The tickets belong to a Customer.

The main problem is that when I create a Ticket with a Customer and a Queue instance hibernate complains that customer_ID is null. The Ticket domain class looks like this:

class Ticket implements Comparable<Ticket> {
    int number;
    boolean isValid;

    static belongsTo = [customer: Customer, queue: Queue]

    public Ticket(Customer customer, Queue queue,int number){
        println "Create ticket, customer: ${customer}, queue:${queue}, number:${number}";
        customer = customer;
        queue = queue;
        number = number;
        isValid = true;
    }
}

The error is in one controller class where I create the Ticket and save it.

//c and q are Customer and Queue instances that have passed null check
Ticket t = new Ticket(c, q, 10);//In the constructor I see the Customer and Queue instances are not null indeed
t.save(flush: true);
if (t.hasErrors()) {
    log.error t.errors;
    return;
}

The error is an empty Customer_ID which I don't quite understand. I have passed the customer and queue into the Ticket constructor but why Grails doesn't seem to match the id when I save it? I've verified that customer id is generated successfully. Please point me to the mistake I've made in the GORM settings.

Message: NULL not allowed for column "CUSTOMER_ID"; SQL statement: insert into ticket (id, version, customer_id, is_valid, number, queue_id) values (null, ?, ?, ?, ?, ?) [23502-176]

Upvotes: 1

Views: 522

Answers (1)

Shashank Agrawal
Shashank Agrawal

Reputation: 25797

This is literally the shadowing problem of the same name of arguments & fields. Just change your constructor like this:

class Ticket implements Comparable<Ticket> {
    int number;
    boolean isValid;

    static belongsTo = [customer: Customer, queue: Queue]

    public Ticket(Customer customer, Queue queue, int number) {
        println "Create ticket, customer: ${customer}, queue:${queue}, number:${number}";
        this.customer = customer;
        this.queue = queue;
        this.number = number;
        this.isValid = true;
    }
}

You have to use this keyword inside the constructor because the domain fields customer and queue and other is shodowed by the constructor parameter.

https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html

Because of customer = customer you are assigning the value of constructor argument to itself instead you should be doing this.customer = customer (same for all others)

Upvotes: 2

Related Questions