域对象引用Grails GORM中的引用表

时间:2010-10-24 17:56:35

标签: groovy gorm grails

我有一个名为User的域对象:

class User{
  String username;
  String firstName;
  String lastName;
  Zipcode zip;
}

我还有一个邮政编码对象:

class Zipcode {
  String zip;
  String city;
  String state;
  Float lat;
  Float long;
}

永远不应修改zipcode表,因为它包含预先填充的静态参考数据

用户属于一个邮政编码。用户输入邮政编码作为用户创建的一部分。

我应该如何建模域对象关系?我想确保GORM不会尝试更新zipcodes。我想确保用户只输入有效的邮政编码。 (可在zipcode表中找到)如何在User对象上配置约束?在控制器中,我执行以下操作:

def userInstance = new User(params) // where params are form values

如何在对象上设置正确的邮政编码?

3 个答案:

答案 0 :(得分:4)

你将让GORM管理zip属性(并限制GORM在第二阶段这样做)。

这也是 mfloryan 的方法所说的;然而,他的方法没有正确区分问题(关注点分离范例):在 MVC (模型 - 视图 - 控制器)模式中,它不是控制器的任务“建模”数据模型,但这是数据访问层的任务(在GORM的情况下 - 域类自己)。

因此,User类将实现如下:

class User {
    String userName
    String firstName
    String lastName
    String zip

    ZipCode retrieveZipCode() {
        ZipCode.findByZip(zip)
    }

static constraints = {
    zip nullable: false, blank: false, matches: /^\d{5}/,
    /* not tested at my machine: */
    validator: {
        if(!retrieveZipCode(it)) {
            return false
        }
    }
}
}

请注意retrieveZipCode()方法。它不被称为getZipCode(),否则,Hibernate会抛出一个关于“缺少setter方法”的异常。您还可以尝试添加zipCode属性,getZipCode()方法(不执行任何操作,或者抛出异常),并将zipCode属性添加到transinients定义。 - 这一切(任何组合)将工作。

另请注意constraints定义:当zip由五位数组成时,它会匹配。 (我相信那是美国的邮政编码格式。) 它还应该确保数据库包含用户邮政编码的条目(语法未测试)。

我稍微更改了ZipCode类(部分是为了避免编译错误):

class ZipCode {
    String zip;
    String city;
    String state;
    Float latitude;
    Float longitude;
}

最后,还有一个集成测试:

class UserTests extends GroovyTestCase {
    def testUserCreation() {
        User user = new User(
            userName: "foo", firstName: "bar", 
            lastName: "baz", zip: "12345")
        assert user.validate()
        assert user.retrieveZipCode()
        user.save()
    }
}

由于

答案 1 :(得分:1)

这听起来像是一个UI问题。在控制器中执行Zipcode对象查找并设置位于用户上的对象。否则,我无法看到在创建用户时如何更改Zipcode

save = {
  params.zip.id = Zipcode.findByZip(params.zip)
  def userInstance = new User(params)
}

save = {
  def userInstance = new User(params)
  userInstance.zip = Zipcode.findByZip(params.zip) 
}

您应该包含一些验证逻辑(如果zip不正确),还要考虑将params.zip重命名为params.userProvidedZip或类似的东西。

答案 2 :(得分:0)

使用域事件回调

   transient beforeUpdate = { 
      // check to make sure that the zip code value remains the same
      // and is never changed... 
   }