Grails/Groovy域类继承强制转换

sgl*_*r87 6 grails groovy inheritance grails-orm

我已经在Grails中使用继承对我的域类建模,如下所示.

abstract class Profile{
}

class Team extends Profile{
}

class User extends Profile{
}

class B{
    static hasMany = [profiles: Profile]
}
Run Code Online (Sandbox Code Playgroud)

稍后在控制器中,当我在某些情况下从B类获取所有配置文件时,我想将一些配置文件转换为Team或User,但我不能,因为我得到了java.lang.ClassCastException或GroovyCastException,尽管它们保存为团队或用户(在数据库中具有属性类).以下是我尝试过的方法:

def team1 = b.profiles.toList()[0] as Team

def team1 = (Team)b.profiles.toList()[0]
Run Code Online (Sandbox Code Playgroud)

当我不写任何类型时它正在工作,因为它在动态语言中是正常的.

def team1 = b.profiles.toList()[0]
Run Code Online (Sandbox Code Playgroud)

但后来我才知道我正在使用哪个班级.无论如何在groovy或gorm中将父类投射给孩子?

cha*_*wit 6

答案是否定的,因为真正的 GORM/Hibernate 实例是一个代理对象。所以它不能直接转换为实体类。

无论如何,这可能会有所帮助:

def team1 = b.profiles.toList()[0]
if(team1.instanceOf(Team)) {
    // I am an instance of Team
    // do something here.
}
Run Code Online (Sandbox Code Playgroud)

  • 不,因为休眠代理不一定是 Java 意义上的子类的“instanceof”。代理类是`b.profiles`(即`Profile`)的_declared_类型的动态生成的子类。[这篇文章](http://blog.springsource.org/2010/07/28/gorm-gotchas-part-3/) 有血腥的细节,它(以及同系列的其他文章)非常值得一读。 (3认同)
  • 总是有`GrailsHibernateUtil.unwrapIfProxy`,它将删除代理包装器并为您提供真实对象(然后您可以投射)但是如果真实对象尚未加载,这将不得不访问数据库。 (3认同)