使用复合键的Grails保存对象引发错误

时间:2014-03-21 15:10:35

标签: grails db2 gorm

因此,我的团队在将现有应用程序从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版本的项目下运行此代码也没有问题。如果有人能对此有所了解,我将非常感激。谢谢

1 个答案:

答案 0 :(得分:0)

经过大量调试和搜索代码后,我设法找到了问题。我们所有的域类都扩展了一个抽象基域,该域具有createdTimestampupdatedTimestamp字段。在进行插入之前,我们设置了两个字段,在进行更新之前,我们更新了updatedTimestamp

问题在于,当我们保存时,新对象有一个空createdTimestamp字段,这就是抛出错误。在代码中添加以检查我们正在创建的GroupProduct对象是否已存在,如果是,则在保存之前将新对象createdTimestamp字段设置为现有对象。现在一切都按预期工作了。

奇怪的是,Grails 1.3.7对此代码没有任何问题。我唯一能想到的是它会自动将新对象与数据库中的现有对象相关联。可能是我在升级过程中发现的最奇怪的行为变化。希望这可以帮助任何遇到类似问题的人。