Grails 2.3和Hibernate4:唯一约束名称冲突

时间:2014-07-17 00:42:29

标签: hibernate grails gorm

更新:这可能会成为Grails错误:https://jira.grails.org/browse/GRAILS-11600


自从我的Grails应用程序升级到Hibernate4后,我遇到了与使用H2和Postgres创建许多我在启动时的独特约束相关的错误。例如:

ERROR hbm2ddl.SchemaExport  - HHH000389: Unsuccessful: alter table bravo add constraint unique_name  unique (bravo_prop, name)
ERROR hbm2ddl.SchemaExport  - ERROR: relation "unique_name" already exists

我通过创建一个新的简单Grails应用程序来研究这个问题。我发现在使用Hibernate4时,在数据库中创建的约束的名称并不是全局唯一的#34;。让我解释一下。

如果我有一个名为" foo"如果具有唯一约束,则数据库中约束的名称可能最终被称为" unique_foo"使用Hibernate4,而使用Hibernate3,它更像是" [tablename] _foo_key"。

这什么时候成为问题? 当我有多个实体对同名属性有唯一约束时,这是一个问题。例如:Entity1有prop" foo"具有唯一约束,Entity2也是如此。在为Entity2创建唯一约束时,SchemaExport将失败。

这里有一些代码可以说明:

class Alpha {
    String name
    String alphaProp
    String alphaProp2

    static constraints = {
        // With Hibernate4.3.5.1|4 and either Grails 2.3.8 or 2.3.11, produces static constraint name: 'unique_name' => BAD
        // With Hibernate3, produces a unique constraint name: 'alpha_alpha_prop_name_key' (notice the entity namespace prefix) => GOOD
        name unique: 'alphaProp'

        // With Hibernate4.3.5.4 and Grails 2.3.11, produces static constraint name: 'unique_name' => BAD
        // With Hibernate3 and Grails 2.3.11 produces unique name: 'alpha_alpha_prop2_alpha_prop_name_key' => GOOD
//        name unique: ['alphaProp', 'alphaProp2']

        // With Hibernate4.3.5.4 and Grails 2.3.11, produces random constraint name such as: 'uk_5h01nufunln3bv2bgxtnr9sxw' => GOOD
        // With Hibernate3 and Grails 2.3.11 produces unique name: 'alpha_name_key' => GOOD
//        name unique: true
    }
}


class Bravo {
    String name
    String bravoProp

    static constraints = {
        // This constraint creation will fail if a constraint by this name was already created by Alpha
        name unique: 'bravoProp'
    }
}

帮助? :)

2 个答案:

答案 0 :(得分:1)

如果您不介意在域中添加未使用的属性,则可以更轻松地解决此问题...

  1. 使用此问题为每个域添加可为空的布尔属性,将该属性命名为uc domainName ,并将其值默认为null。例如:
  2. Boolean ucBravo = null
    
    1. 使用新属性名称添加唯一约束,并使其可为空。例如:
    2. ucBravo nullable: true
      ucBravo(unique: ['name','bravoProp'])
      

      没有必要填充或findBy新的'ucBravo'属性,因为它默认为null。但是使用它作为域约束中的第一个属性将导致数据库约束名称是特定于域的 - 如'unique_uc_bravo'而不是'unique_name'。

      包含这些更改的Bravo域示例:

      class Bravo {
          String name
          String bravoProp
          Boolean ucBravo = null
      
          static constraints = {
              // creates a Database constraint named like 'unique_uc_bravo'
              ucBravo nullable: true
              ucBravo (unique: ['name','bravoProp'])
          }
      }
      

答案 1 :(得分:0)

我从未收到过Grails开发人员的回复,因此我会将此问题视为一个错误:https://jira.grails.org/browse/GRAILS-11600

如果您要使用grails-data-mapping软件包,请参阅我应用的解决方法的JIRA问题。不是很漂亮,但完成了工作。