groovy的属性缺失在grails3中不起作用

groovy的属性缺失在grails3中不起作用,grails,groovy,Grails,Groovy,我已经在src/groovy abstract class BaseDomain { def storage = [:] def propertyMissing(String name, value) { storage[name] = value} def propertyMissing(String name) { storage[name] } } 我已经创建了以下域类 class Student extends BaseDomain { String f

我已经在
src/groovy

abstract class BaseDomain {
    def storage = [:]
    def propertyMissing(String name, value) { storage[name] = value}
    def propertyMissing(String name) { storage[name] }
}
我已经创建了以下域类

class Student extends BaseDomain {
    String firstName
    String lastName
    //....
}
但是,当我尝试向student对象动态添加属性时,它会抛出异常,但它应该是groovy作为动态编程语言的本质

我使用Groovy 2.4.10、Grails 3.2.9和IntelliJ


我是否缺少application.yml中的任何配置,这是我在Grails 3中做的第一个项目,之前我使用Grails 2.5.x,然后我没有问题,它工作正常。

Grails 3广泛使用特性来混合方法、基类和工件类(域类、控制器等)的接口一般来说,行为是相同或非常相似的,但也有类似的情况,即引擎盖下的实现会影响某些事情的工作方式

如果您使用反编译器或反射API,您可以看到您的域类实现了几个实际上是Groovy特性的接口,这里感兴趣的是
org.grails.datastore.gorm.GormEntity
,因为它是
def propertyMissing(String name)
实现的源代码。这是为了支持多个数据源,例如,如果有第二个名为
“mongo”
的数据源,那么您可以使用该数据源在从另一个数据源检索的实例上使用语法
student.mongo.theMethodName(…)
进行实例方法调用。由于该方法是在trait中定义的,因此将调用trait方法并忽略您的方法

trait可以尝试调用您的方法,但它不一定存在(在本例中甚至不可能,因为这不是一种常见的技术),因此需要仔细实现

但是您可以通过利用Groovy中的逻辑来解决这个问题,当有多个方法具有来自不同来源的相同签名时,该怎么办。最后声明的trait(在通过
实现的类声明中)中的方法就是调用的方法。Traits可以调用
super.methodname(…)
来“链”调用其他也声明该方法的Traits

因此,将
BaseDomain
从抽象基类更改为trait:

package ...

import org.grails.datastore.gorm.GormEntity

trait DynamicProperties<D> implements GormEntity<D> {

   def dynamic = [:]

   def propertyMissing(String name, value) {
      if (!propertyIsDatasource(name)) {
         dynamic[name] = value
      }
   }

   def propertyMissing(String name) {
      if (propertyIsDatasource(name)) {
         super.propertyMissing(name)
      }
      else {
         dynamic[name]
      }
   }

   boolean propertyIsDatasource(String name) {
      false
   }
}
包。。。
导入org.grails.datastore.gorm.GormEntity
特性动态特性实现了GormEntity{
def dynamic=[:]
def propertyMissing(字符串名称、值){
如果(!propertyIsDatasource(名称)){
动态[名称]=值
}
}
def propertyMissing(字符串名称){
if(propertyIsDatasource(名称)){
super.propertyMissing(名称)
}
否则{
动态[名称]
}
}
布尔属性数据源(字符串名称){
假的
}
}
实施而不是扩展:

package ...

class Student implements DynamicProperties<Student> {
   String firstName
   String lastName
}
包。。。
班级学生实现动态属性{
字符串名
字符串姓氏
}
不幸的是,
GormEntity
需要类名,因此需要在具体类中冗余地包含该类名

由于
DynamicProperties
扩展了
GormEntity
,因此它将位于“链”的前面,因此将首先调用它


任何使用多个数据源的域类都需要使用自定义逻辑重写
propertyIsDatasource
方法,以确保数据源名称由GORM处理。只需在该域类中用相同的签名声明它。如果您知道您永远不会在任何域类中使用多个数据源,那么您可以删除所有这些逻辑。

什么异常?PropertyMissingException编辑问题以包括异常和stacktrace,在提供的信息如此之少的情况下很难诊断谢谢先生。非常感谢你。很高兴得到你的答复。通过关注你的帖子,我解决了很多问题,学到了很多。很高兴得到回答。这个解释太棒了。它工作起来很有魅力