grails v3.2.6 / gorm嵌入类在同一个域class.groovy中创建虚拟DB表

时间:2017-02-14 15:21:08

标签: grails gorm

在grails / gorms文档中,它说你可以将嵌入式类放在与顶级父域类相同的域类文件中 - 这可以从代码角度运行,但它仍然生成一个GeoAddress表,以及嵌入列进入源Venue表。测试数据在场地中输入 - geoAddress表保持为空。

文档意味着不应该生成这个嵌入式表。我可以尝试将GeoAddress移动到它自己的src / groovy文件中,因此它不在grails-app / domain文件夹中,但是我必须记住我已经完成了这个'。它会更加清洁'保持与包含类相同的文件。

除了将GeoAddress本身提升回完整的域类之外 - 如何在嵌入使用时告诉gorm不为它生成表格?

我在grails-app / domain文件夹中的venue.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
    }
}

3 个答案:

答案 0 :(得分:1)

好的 - 我确实找到了一种方法,将geoLocation用作嵌入式并停止创建表格。

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

我不确定这是一个错误还是什么 - 但是在第5.2节 - gorm中的组合中的建议中,grails文档是不正确的,

  

如果你在一个单独的Groovy文件中定义Address类   grails-app / domain目录你也会得到一个地址表。如果你   不希望发生这种情况使用Groovy定义多个的能力   每个文件的类,并包含Person类下面的Address类   在grails-app / domain / Person.groovy文件中

修改后的类如下所示。当你想创建其中一种时,格式(用于bootstrap / tests)看起来像是新的Venue.GeoLocation(...)

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})$/
        }
    }
}

答案 1 :(得分:0)

基于类名的Grails表生成,尝试将嵌入式设置为Collection而不是Class。

答案 2 :(得分:0)

我似乎已将帖子放在基本相同的问题上 - 粗心。另见can't get cascade save nor delete on embedded class ref to work

然而要重复。让嵌入式类位于grails-app / domain文件夹中的主类下面,不会阻止生成嵌入式类(如文档中所暗示的那样)。

所以Gorm继续前进并创建了一个Venue和一个GeoLocation(我的例子在这里)。然而,使用不是我所期望的,这也是测试失败的原因。

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

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

所以当测试执行GeoLocation.list()/ get()时,它会找到该表中的行而不是查看场地嵌入列。

找不到一个很好的方法。阻止geoLocation进入数据库的唯一方法是将定义移出域文件夹并放入src / groovy。但是,然后你的域模型被分成两个子树,并且在域文件夹之外获取gorm验证更加繁琐。

我认为我必须接受使用GeoLocation作为完整的域类而不是使用嵌入式 - 并接受加入成本。至少这种方式模型/测试工作正如您所期望的那样。

结果不确定嵌入是一个明智的建模决策,我建议不要使用除非你真的必须