因此,我的团队在将现有应用程序从Grails 1.3.7升级到2.1.0时遇到了多个问题。尝试保存具有基于另外两个域对象的复合键的域类对象时,会出现最新的问题。
我们将Grails挂在遗留数据库上,我们无法轻易更改,因此所有域类都有自定义映射来与它连接。以下是相关域类的快速,精简版本。
Class Product {
Short prodKey
String name
static hasMany = [groupProduct: GroupProduct]
//Also includes mapping to legacy db and simple constraints
}
Class Group {
Short groupKey
String name
static hasMany =[ groupProduct: GroupProduct]
//This domain class has several other mappings and variables, but they are not relevant
}
Class GroupProduct {
Group group
Product product
Character indicator
static belongsTo = [Product,Group]
static mapping = {
id composite: ["group", "product"]
group lazy:false, column:"GROUP_KEY", joinTable:"GROUP"
product lazy:false, column:"PROD_KEY", joinTable:"PRODUCT"
version false
}
//Only constraint is indicator is Y or N
}
在应用程序中,用户可以通过复选框列表为组打开或关闭多个产品。参数包含groupKey和所有已检查产品的列表。控制器获取指定组的实例,然后获取所有产品的列表。产品与参数中的列表进行匹配,每次找到匹配时,将指标设置为' Y'制作GroupProduct对象,否则制作GroupProduct对象时将指标设置为' ; N'
Class GroupProductController{
//allowedMethods and other actions...
def update = {
def groupInstance = Group.get(params.GroupId)
def groupProducts= []
def products= Products.list()
products.each{
def indicator = ...//code to get value of check box for this Product. Returns either Y or N, works as expected
def groupProduct= new GroupProduct(group:groupInstance ,
product:it,
indicator: indicator)
groupProducts.add(groupProduct)
}
groupInstance.discard()
groupProducts.each{
it.save(failOnError: true, flush:true)//This line throws a DB2 SQL error. SQLCODE=-407
}
}
}
产生的错误是:
org.hibernate.util.JDBCExceptionReporter|DB2 SQL Error: SQLCODE=-407, SQLSTATE=23502, SQLERRMC= , DRIVER=3.50.152
org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener|Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not update: [GroupProduct#component[group,product]{product=Product#1, group=Group#938926168}]
at com.controllers.ProductGroupController$_closure2_closure8.doCall(ProductGroupController.groovy:86)
at com.nationwide.nas.beam.controllers.ProductGroupController$_closure2.doCall(ProductGroupController.groovy:79)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: com.ibm.db2.jcc.b.lm: DB2 SQL Error: SQLCODE=-407, SQLSTATE=23502, SQLERRMC= , DRIVER=3.50.152
at com.ibm.db2.jcc.b.wc.a(wc.java:575)
at com.ibm.db2.jcc.b.wc.a(wc.java:57)
at com.ibm.db2.jcc.b.wc.a(wc.java:126)
at com.ibm.db2.jcc.b.tk.b(tk.java:1593)
at com.ibm.db2.jcc.b.tk.c(tk.java:1576)
at com.ibm.db2.jcc.t4.db.k(db.java:353)
at com.ibm.db2.jcc.t4.db.a(db.java:59)
at com.ibm.db2.jcc.t4.t.a(t.java:50)
at com.ibm.db2.jcc.t4.tb.b(tb.java:200)
at com.ibm.db2.jcc.b.uk.Gb(uk.java:2355)
at com.ibm.db2.jcc.b.uk.e(uk.java:3129)
at com.ibm.db2.jcc.b.uk.zb(uk.java:568)
at com.ibm.db2.jcc.b.uk.executeUpdate(uk.java:551)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
... 5 more
尝试保存GroupProduct对象时发生错误。据IBM称,错误代码-407是由AN UPDATE, INSERT, OR SET VALUE IS NULL, BUT THE OBJECT COLUMN column-name CANNOT CONTAIN NULL VALUES
引起的。但是,GroupProducts的变量实际上都不为null。 Group和Product实例直接从数据库中提取,这意味着它们已经过验证,不应该有任何约束违规,我可以看到指标字段设置正确。
在原始1.3.7版本的项目下运行此代码也没有问题。如果有人能对此有所了解,我将非常感激。谢谢
答案 0 :(得分:0)
经过大量调试和搜索代码后,我设法找到了问题。我们所有的域类都扩展了一个抽象基域,该域具有createdTimestamp
和updatedTimestamp
字段。在进行插入之前,我们设置了两个字段,在进行更新之前,我们更新了updatedTimestamp
。
问题在于,当我们保存时,新对象有一个空createdTimestamp
字段,这就是抛出错误。在代码中添加以检查我们正在创建的GroupProduct对象是否已存在,如果是,则在保存之前将新对象createdTimestamp
字段设置为现有对象。现在一切都按预期工作了。
奇怪的是,Grails 1.3.7对此代码没有任何问题。我唯一能想到的是它会自动将新对象与数据库中的现有对象相关联。可能是我在升级过程中发现的最奇怪的行为变化。希望这可以帮助任何遇到类似问题的人。