Defining OR Condition with grails criteria api

micha picture micha · Jan 21, 2013 · Viewed 9.7k times · Source

I have the following domain objects:

class User {
    String name
    Transaction transaction

    static constraints = {
        transaction nullable: true
    }
}

class Transaction {        
    boolean successful
    User user        
    static belongsTo = User
}

I want to select all users that have no successful transaction. This means I want the users without any transaction (transaction == null) and the users that have a transaction with the successful value false (transaction.successful == false). I want to do this with the Criteria API (because this can be combined with other conditions based on user input).

I tried this:

def c = User.createCriteria()
def results = c {
    or {
        isNull 'transaction'
        transaction {
            eq 'successful', false
        }
    }
}

However this gives me only the users that have a transaction (with the successful value false). But I do not get the users where transaction is null

The following code shows how I created some sample data:

def createUserAndTransaction(String name, Boolean successful = null) {
    User u = new User(name: name)
    if (successful != null) {
        Transaction t = new Transaction(user: u, successful: successful)
        u.setTransaction(t)
    }
    u.save()
}

def init = { servletContext ->
    createUserAndTransaction 'john', true
    createUserAndTransaction 'mike', false
    createUserAndTransaction 'pablo'
}

My criteria query only returns mike in this case. But I want mike and pablo. What am I missing?

Answer

James Kleeh picture James Kleeh · Jan 22, 2013

So the problem is that it defaults to an inner join. You have to create an alias for the table and define its join type:

createAlias("transaction", "t", CriteriaSpecification.LEFT_JOIN)

or {
    isNull("t")
    eq("t.successful", false)
}