我有一个名为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
如何在对象上设置正确的邮政编码?
答案 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...
}