Reputation: 136
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
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
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