如何在 grails 域子类中添加对继承属性的约束

Posted

技术标签:

【中文标题】如何在 grails 域子类中添加对继承属性的约束【英文标题】:How to add constraints on inherited properties in a grails domain sub-class 【发布时间】:2011-04-25 10:49:12 【问题描述】:

这是我想做的:

class A 
  String string
  static constraints = 
    string(maxSize:100)
  


class B extends A 
  static constraints = 
    string(url:true)
  

所以类 A 应该有 一些 约束,而 B 应该在同一属性上具有 相同的加额外 约束。

但我无法让它工作,我可以想象它会与每层次结构表的概念发生冲突。

所以我尝试通过引入具有 B 类约束的 Command 对象来解决该问题,该约束可以在 B 类的构造函数中进行验证。但是,Command 对象似乎只能在控制器中使用(grails 一直说有没有 .validate() 方法)。

所以我的问题是:使用 grails 约束解决这个问题的最优雅的方法是什么(不是手动重新实现验证)?可能是……

切换到 Table-per-Sub-Class 概念? 以某种方式使命令对象在 Domain 类中工作? 还有其他方法吗?

编辑:我可以在子类中定义所有约束,重复父类的约束,甚至在父类中根本没有约束。但该解决方案应该适用于同一父类的多个子类(具有不同的约束)。

【问题讨论】:

我不确定每个约束都会以这种方式工作,因为默认情况下继承的类映射到同一个数据库表。因此,如果您的 C 类在 Cc 上具有非空的唯一约束,它将对整个表 A 施加 DB 表约束 - 所有类都将存在 c 字段,并且对于除 C 实例之外的任何内容都将为空。 是的,这就是我使用 Table-per-Sub-Class 的原因。 【参考方案1】:

你可以使用

    class B extends A 
       static constraints = 
          importFrom A
          //B stuff
       
    

如http://grails.org/doc/latest/ref/Constraints/Usage.html中所述

【讨论】:

【参考方案2】:

2.x 中的样子:

由于约束是由某些 ConstraintsBuilder 执行的闭包,我会尝试从 B 调用它,例如

class B extends A  
  static constraints =  
    url(unique: true)
    A.constraints.delegate = delegate  # thanks Artefacto
    A.constraints()
   

【讨论】:

关闭。不过,您必须先更改A.constraints 的代表:A.constraints.delegate = delegate。但是感谢您为我指明了正确的方向。 @Artefacto - 您能否发布有效的答案,或编辑此答案以使其有效?我知道其他人也有这个问题。谢谢! 我已经用 grails 2.0.4(使用 grails 控制台)尝试过它,但它不起作用,它在 A.contraints 没有委托属性的阶段引发错误【参考方案3】:

基本上我看不出它是怎么做到的。

在设计方面,域类实际上映射了数据库表的结构。约束实际上会生成数据库约束。因此,您正在尝试制作多个对象,这些对象将在同一张表上生成不同的约束。

我认为更好的方法是创建一个具有最简单约束子集的域对象,然后使用不同的命令对象来微调要传递给域的确切约束。

您还可以使用验证器:在约束中为不同的对象类型微调不同的约束(类似于域中的类型列并根据不同的类型进行不同的验证)。

【讨论】:

【参考方案4】:

您需要重新声明超类约束,因为它是一个静态 clojure(静态属性和静态方法不会被子类继承),因此它不会被 GORM 映射。

干杯。

【讨论】:

以上是关于如何在 grails 域子类中添加对继承属性的约束的主要内容,如果未能解决你的问题,请参考以下文章

Grails 域模型中的继承导致重复的外键

Grails 唯一约束 - 它可以双向工作吗?

如何使事务在 Grails 中工作

java子类从父类继承某个属性,怎么添加特定的注解不影响父类

Grails 数据库迁移插件静默无法添加非空约束

日期验证的 Grails 最小约束