grails v3.2.6/gorm在同一域类中嵌入类。groovy创建虚拟数据库表

grails v3.2.6/gorm在同一域类中嵌入类。groovy创建虚拟数据库表,grails,gorm,Grails,Gorm,在grails/gorms文档中,它说您可以将嵌入的类与顶级父域类放在同一个域类文件中——这从代码角度来看是可行的,但它仍然会生成一个GeoAddress表,并将列嵌入到源表中。测试数据输入场馆-地理地址表保持为空 文档说明不应生成此嵌入表。我可以尝试将GeoAddress移动到它自己的src/groovy文件中,这样它就可以从grails app/domain文件夹中移出,但是我必须“记住我已经这样做了”。将它与包含的类保存在同一个文件中会更“干净” 除了自己将GeoAddress提升回完整域

在grails/gorms文档中,它说您可以将嵌入的类与顶级父域类放在同一个域类文件中——这从代码角度来看是可行的,但它仍然会生成一个GeoAddress表,并将列嵌入到源表中。测试数据输入场馆-地理地址表保持为空

文档说明不应生成此嵌入表。我可以尝试将GeoAddress移动到它自己的src/groovy文件中,这样它就可以从grails app/domain文件夹中移出,但是我必须“记住我已经这样做了”。将它与包含的类保存在同一个文件中会更“干净”

除了自己将GeoAddress提升回完整域类之外,我如何告诉gorm在嵌入其使用时不为其生成表

grails app/domain文件夹中的my venture.groovy

class Venue {

    String name
    LocalDate dateCreated
    LocalDate lastVisited
    LocalDate lastUpdated
    GeoAddress location
    Collection posts


    static hasMany = [posts:Post]           
    static embedded =['location']

    static constraints = {
        lastVisited nullable:true
        location    nullable:true, unique:true
        posts       nullable:true
    }
    static mapping = {
        location cascade: "all-delete-orphan", lazy:false, unique:true 
         posts    sorted: "desc", cascade:"save-update"


    }
}


class   GeoAddress {

    String addressLine1
    String addressLine2
    String addressLine3
    String town
    String county
    String country = "UK"
    String postcode

    //adds addTo/removeFrom methods to venue
    static belongsTo = Venue

    static constraints = {
        addressLine1 nullable:true
        addressLine2 nullable:true
        addressLine3 nullable:true
        town         nullable:true
        county       nullable:true
        country      nullable:true
        postcode     nullable:true
    }
}

Grails表的生成基于类名,尝试将其作为集合而不是类嵌入。

我似乎在本质上相同的问题上发表了文章-粗心。另见

不过,我们需要重新发行。让嵌入类位于grails app/domain文件夹中主类的下面,并不会阻止生成嵌入类(正如文档中所暗示的那样)

所以Gorm走到了最前面,为您创建了一个地点和地理位置(我在这里的例子)。然而,使用也不是我期望的,这就是测试失败的原因

如果将新的地理位置作为构造函数arg添加到场馆,则临时实例将保存在同一表中嵌入位置列的场馆表中。如果删除场馆,则整个行将从场馆表中删除

但是,如果您首先创建一个GeoLoaction并将其保存(),它实际上存储在GeoLocation表中。然后将其添加到场馆会更新场馆表中的列

因此,当测试执行GeoLocation.list()/get()时,它会在该表中查找该行,而不是查找嵌入的列

我找不到一个好办法。阻止地理定位进入数据库的唯一方法是将定义移出域文件夹并放入src/groovy。但是,您的域模型被分为两个子树,要在domains文件夹之外启动gorm验证更容易实现

我想我不得不接受使用地理定位作为完整的域类,而不是使用嵌入式,并接受加入成本。至少这样,模型/测试可以像您预期的那样工作


结果不确定embedded是否是一个明智的建模决策,我建议不要使用,除非你真的必须这样做。好的-我确实找到了一种方法,将地理位置作为嵌入式使用,并停止创建表

我必须将Geolocation设置为侧场地的静态内部类。当您这样做并运行应用程序时,您不会在数据库中获得额外的虚假域表。它必须是静态的内部类,因为地理位置有一个静态的约束声明

我不确定这是一个bug还是什么——但是grails文档在第5.2节“gorm中的合成”中的建议是不正确的,它说

如果在 grailsapp/domain目录您还将获得一个地址表。如果你 如果不希望发生这种情况,请使用Groovy定义多个 每个文件的类,并包括Person类下面的Address类 在grails app/domain/Person.groovy文件中

修改后的类如下所示。当您想要创建其中一个时,格式(用于引导/测试)将类似于new-vinge.GeoLocation(…)


不知道您是否尝试将其作为抽象类,以及这是否会起作用并保持不变尝试将其声明为
抽象类GeoAddress
它肯定不是抽象类-因为我必须创建它的实例以添加到场地构造函数中。你不能使用new(),因此我认为这不起作用。如果你非常关心表创建集dbCreate-是否从域模型自动生成数据库-其中一个是“create drop”,“create”,“update”或“validate”我假定update或甚至validate不创建然后运行
grails导出模式
并手动创建表我在火车上看了看,我在mo使用内存中的dev H2 db。我发现了这些。尽管文档建议将嵌入类与父类放在同一个groovy文件中(即我使用嵌入位置定义了场地,地理位置遵循场地定义),但这会为地理位置创建一个表。找出测试失败的原因。如果在“场地构造器”中添加新的地理位置并保存,则条目将与场地一起写入,正如您所期望的那样,所有条目都在同一个表中。但是,如果先创建位置并保存,它会在地理位置表中写入一行。因此,当您删除场地时,它(以及嵌入的位置)将被删除,但是如果您自己保存了一个位置,它将被写入地理位置表。因此GeoLocation.list()会找到一个条目,测试失败不能是一个集合,因为它是1:1-一个场地有一个位置。因此,与尝试实现类似效果的过程相比,
连接成本
不起作用,但是嵌入域类仍然不确定如果引入缓存,如果使用
String getAddressLine1(){return location.addressLine1}之类的东西,您会觉得成本是多少
场馆
类中,为您想要快速访问的每个对象-然后使用hql地图从场馆连接位置清晰地抓取特定元素,因此选择新地图(v.name,l.addessLine1)从场馆到加入地点,这样成本就降到了最低——正如我所说的,这些类型的加入太普遍了,而嵌入的场景可能强调了错误的考虑——我可以承受加入成本。我真正关心的是,读了这些文件后,我
class Venue implements Serializable {

    String name
    LocalDate dateCreated
    LocalDate lastVisited
    LocalDate lastUpdated
    GeoAddress location
    Collection posts

    //static hasOne = [location:GeoAddress]   //, temp:TempLocation
    static hasMany = [posts:Post]           //but doesn't really own thats with user
    static embedded =['location']

    static constraints = {
        lastVisited nullable:true
        location    nullable:true, unique:true
        posts       nullable:true
    }
    static mapping = {
        location cascade: "all-delete-orphan", lazy:false, unique:true  //eager fetch strategy
        posts    sorted: "desc", cascade:"save-update"

        //comment out for now
        //posts joinTable: [name:"venue_posts", key:"venue_id", column:"posts", type:Post]
    }

    static class GeoAddress {

        String addressLine1
        String addressLine2
        String addressLine3
        String town
        String county
        String country = "UK"
        String postcode

        //adds addTo/removeFrom methods to venue
        static belongsTo = Venue

        static constraints = {
            addressLine1 nullable:true
            addressLine2 nullable:true
            addressLine3 nullable:true
            town         nullable:true
            county       nullable:true
            country      nullable:true
            postcode     nullable:true,
                    matches: /^([gG][iI][rR] {0,}0[aA]{2})|([a-pr-uwyzA-PR-UWYZ](([0-9](([0-9]|[a-hjkstuwA-HJKSTUW])?)?)|([a-hk-yA-HK-Y][0-9]([0-9]|[abehmnprvwxyABEHMNPRVWXY])?)) ?[0-9][abd-hjlnp-uw-zABD-HJLNP-UW-Z]{2})$/
        }
    }
}