【问题标题】:Questions about implementing Domain class relationships & constraints in Grails关于在 Grails 中实现域类关系和约束的问题
【发布时间】:2026-01-27 14:10:01
【问题描述】:

使用 ArgoUML,我很快创建了几个域类(Person、Store、Product)及其关系的简单表示。

我正在努力实现这些关系。以下是我对 Person 域的初始方法,但似乎我遗漏了一些重要的东西。

class PersonToPerson {
    Person from
    Person to
    String relation

    static constraints = {
         relation(inList:["Friend to", "Enemy of", "Likes", "Hates"])
    }
    static belongsTo = [ Person ]
}


class Person {
    String firstName
    String secondName
    .
    .
    .
    static hasMany= [ personToPerson:PersonToPerson, 
                      personToStore:PersonToStore ]
}

编辑:为了清楚起见更新了问题


在思考问题后,我认为我有更好的方式来提出问题。在上面 PersonToPerson 的实现中,我将关系作为一个简单的字符串。我希望用户能够从约束中定义的唯一关系列表中选择 PersonToPerson 的字符串值。所以这就引出了问题......

  1. 是否应该将 personToPerson 和 personToStore 合并到一个关系类型列表中?还是应该如图所示保持独立的列表?
  2. 允许用户向关系约束添加新值的机制是什么?

【问题讨论】:

    标签: grails dns constraints orm


    【解决方案1】:

    1) 领域模型

    让您的代码保持简单。不要创建通用数据模型。这是下地狱的方式。当您将 personToPerson 和 personToStore 分开时,遵循您的代码会容易得多。

    实际上建议的解决方案可以同时访问作为合并列表和独立列表的关系。

    对于这个问题,我会使用inheritance feature in GORM

    您的课程如下所示:

    class Person {
        String name
        static hasMany = [personToPerson:PersonToPerson,
                          personToProduct:PersonToProduct,
                          personToStore:PersonToStore]
    
        static mappedBy = [personToPerson:"from"]
    }
    
    class Product{
        String productName
    }
    
    class Relationship{
        String note
    }
    
    class Store{
        String storeName
    }
    
    class PersonToPerson extends Relationship{
        Person from
        Person to
        String relation
    
        static constraints = {
             relation(inList:["Friend to", "Enemy of", "Likes", "Hates"])
        }
        static belongsTo = [ from:Person ]
    }
    
    class PersonToProduct extends Relationship{
        Person person
        Product product
        String relation
    
        static constraints = {
             relation(inList:["likes", "dislikes"])
        }
        static belongsTo = [ person:Person ]
    }
    
    class PersonToStore extends Relationship{
        Person person
        Store store
        String relation
    
        static constraints = {
            relation(inList:["Stock person", "Owner", "Manager", "Patron"])
        }
        static belongsTo = [ person:Person ]
    }
    

    人员、产品和商店的数据库模式是常见的。但是对于关系域看起来像这样:

    关系

    Field      Type         Null Default 
    id         bigint(20)   No   
    version    bigint(20)   No   
    note       varchar(255) No   
    class      varchar(255) No   
    person_id  bigint(20)   Yes  NULL  
    product_id bigint(20)   Yes  NULL  
    relation   varchar(8)   Yes  NULL  
    from_id    bigint(20)   Yes  NULL  
    to_id      bigint(20)   Yes  NULL  
    store_id   bigint(20)   Yes  NULL   
    

    关系域使得访问所有关系域成为可能,只需一个域。

    2) 约束

    只需将 inList 切换到 validator。比您可以将约束存储在文件或数据库中。 请参阅documentationfile example

    示例如何在 DB 中存储约束值。首先创建一个域对象。

    class Constrain{
        String name
        String type
    }
    

    比领域类看起来:

    class PersonToPerson extends Relationship{
        Person from
        Person to
        String relation
    
        static constraints = {
             relation(nullable:false, validator:{val, obj ->
                 def list = Constrain.findAllByType('person').collect{it.name}
                 return list.contains(val)
             })
        }
        static belongsTo = [ from:Person ]
    }
    

    【讨论】:

      【解决方案2】:

      看起来不错。您可能需要考虑 PersonToPerson 类中的 belongsTo。

      另外,你有很多人应该是:[ personToPersons:PersonToPerson....

      【讨论】:

      • 感谢 Dean,我采纳了您的建议,然后更新了问题以使其更清晰。