Joakim
Joakim

Reputation: 136

SQLException in Grails save() method

I've a grails (2.2.4) application deployed to a JBoss (5.2) server with DB setup for an Oracle DB:

datasource { 
    dbCreate = 'update'
    jndiName = 'java:XXX
}

I also have two domain objects:

class A {
    def name
    static hasOne = [b:B]
    static constraints = { 
        b unique: true
        name unique: true
    }
}

class B {
    A a
    static belongsTo = [A]
}

And finally a service for finding/creating an instance of A:

A createA(String name) {
    def a = A.findByName(name)
    if(!a) {
        a = new A(name: name)
        a.b =  new B(a: a)
        a.save() <-- This causes the ERROR. Tried a.save(flush:true), a.save(failOnError:true) and a.save(flush:true, failOnError:true)
    }
    return a
}

When using Hibernates own H2 DB and testing local with both grails run-app and grails run-war this work fine, but after integrating with the Oracle DB and deploying to JBoss server I get the following error:

Hibernate operation: could not execute query; uncategorized SQLException for SQL [
    select this_.id as id1_0_, this_.version as version1_0_, this_.name as name1_0_ 
    from a this_ 
    where this_.id=?]; 
SQL state [99999]; error code [17041]; 
Missing IN or OUT parameter at index:: 1; 
nested exception is java.sql.SQLException: Missing IN or OUT parameter at index:: 1

Anyone got an idea of what is going wrong here?

Upvotes: 0

Views: 433

Answers (2)

Joakim
Joakim

Reputation: 136

I managed to fix the problem. I had to place the unique attributt in the child relation of the one-to-one mapping as this:

class A {
    def name
    static hasOne = [b:B]
    static constraints = { 
        // b unique: true <-- REMOVED
        name unique: true
    }
}

class B {
    A a
    static belongsTo = [A]
    static constraints = {
        a unique: true // <-- ADDED
    }
}

Not really sure why, but it worked.

Upvotes: 0

elixir
elixir

Reputation: 1442

Considering that you can change your domain class, I would make following changes to your domain class.

class A {
    def name
    static hasOne = [b:B]
    static constraints = { 
        //b unique: true    // try commenting this line out
        name unique: true   
    }
}

class B {
    A a
    // static belongsTo = [A] // I don't think you need this.
}

On your service,

A createA(String name) {
    def a = A.findByName(name)
    if(!a) {
        a = new A(name: name).save(flush:true, failOnError:true)
        //a.b =  new B(a: a)  // this feels going around in circles.
        new B(a: a).save(flush:true, failOnError:true)

        // you may only need one save() and the changes will cascade. 
        //I will leave that upto you which save() cascades and which one doesn't.  
    }
    return a
}

Also you can look into this http://docs.grails.org/2.3.1/ref/Domain%20Classes/findOrCreateBy.html to simplify your logic.

Upvotes: 1

Related Questions