alt text http://i41.tinypic.com/13ykqvb.png
这里DealerID可以为空,Car,轮胎是独一无二的。
我注意到的问题是: Grails在唯一约束中忽略空值。
答案 0 :(得分:3)
我不认为这个问题很清楚,但这可能是Grails中的bug。
答案 1 :(得分:2)
static constraints = {
dealerID nullable:true;
carID unique:'dealerID', blank:false;
tyreID unique:'carID';
}
这不会按预期工作。这将使carID仅在dealerID范围内唯一。 tyreID在'carID'范围内是唯一的。这意味着当输入这个完全有效的行时验证将失败:
CarID TyreID DealerID 01 02 NULL Existing row 01 02 95 New row is rejected
这是因为TyreID不是唯一的 - 它与现有的CarID冲突。我们希望将唯一约束应用于所有指定字段的范围
据我所知,最新版本的Grails(1.3.7)
仍然存在这个问题在您的域类中,使用CriteriaBuilder为查找现有记录的字段编写自定义验证器:
class MyClass { ... static constraints = { ... carID( validator: { Integer carID, MyClass thisInstance -> def existingRecord = MyClass.withCriteria(uniqueResult:true){ ne('id', thisInstance.id) if (thisInstance.tyreID) { eq('tyreID', thisInstance.tyreID) } else { isNull('tyreID') } if (thisInstance.dealerID) { eq('dealerID', thisInstance.dealerID) } else { isNull('dealerID') } }) if (existingRecord) { return ['myClass.duplicate', existingRecord.id] } else { return true } } )
并在您的邮件属性中,您可以提醒用户此记录与特定记录冲突:
message.properties ... myClass.duplicate = {0} is identical to existing record {3}
这是一个hacky解决方案,需要一个可能不必要的数据库命中,看起来很难看。我不喜欢它,但它有效。
答案 2 :(得分:0)
我知道这在游戏中已经晚了,但为了使组合独特,我会提出这样的约束:
static constraints = {
dealerID nullable:true;
carID unique:'dealerID', blank:false;
tyreID unique:'carID';
}
这应该确保即使Grails忽略了由于dealerID为null而对carID的唯一约束,你也不会得到冲突的carID和tyreID的组合。 至少我认为这是有效的。
答案 3 :(得分:0)
这是一个古老的话题,但我认为无论如何我都会分享我可靠的解决方案。它使用了一个额外的列,因此它需要一点额外的存储空间,但保持性能的速度和没有可空的空间一样快。匹配您的示例,您添加/更改(假设您的ID是简单的字符串由于空白约束和简单):
@foreach (var item in Model)
{
<div class="ratestar" id="abc" >
<input type="radio" name="example" class="rating" value="1" />
<input type="radio" name="example" class="rating" value="2" />
<input type="radio" name="example" class="rating" value="3" />
<input type="radio" name="example" class="rating" value="4" />
<input type="radio" name="example" class="rating" value="5" />
</div>}
约束字段总是有一个值,当它与唯一性无关时,它不会妨碍你。