我正在使用JPA 2.0 / Hibernate验证来验证我的模型。我现在有一种情况,必须验证两个字段的组合:
public class MyModel {
public Integer getValue1() {
//...
}
public String getValue2() {
//...
}
}
如果getValue1()
和getValue2()
都是null
,则模型无效,否则有效。
如何使用JPA 2.0 / Hibernate执行此类验证?使用简单的@NotNull
注释,两个getter都必须为非null才能通过验证。
答案 0 :(得分:74)
对于多个属性验证,您应该使用类级别约束。从 Bean Validation Sneak Peek part II: custom constraints:
类级约束
有些人表达了担忧 关于申请的能力 约束跨越多个 属性,或表达约束 这取决于几个属性。 经典的例子是地址 验证。地址错综复杂 规则:
- 街道名称有些标准,必须有长度限制
- 邮政编码结构完全取决于国家/地区
- 城市通常可以与邮政编码相关联,并且可以进行一些错误检查 完成(如果验证 服务是可以访问的)
- 因为这些相互依赖性,一个简单的属性级别约束就是这样 适合该法案
Bean提供的解决方案 验证规范是双重的:
- 它提供了强制在一个约束之前应用一组约束的能力 通过其他一组约束 使用组和组序列。 该主题将在本课程中介绍 下一篇博客文章
- 它允许定义类级约束
类级别约束是常规的 约束(注释/ 实施二人组)适用于 阶级而不是财产。说过 不同的是,类级约束 接收对象实例(相反 比
isValid
中的属性值。@AddressAnnotation public class Address { @NotNull @Max(50) private String street1; @Max(50) private String street2; @Max(10) @NotNull private String zipCode; @Max(20) @NotNull String city; @NotNull private Country country; ... } @Constraint(validatedBy = MultiCountryAddressValidator.class) @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface AddressAnnotation { String message() default "{error.address}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } public class MultiCountryAddressValidator implements ConstraintValidator<AddressAnnotation, Address> { public void initialize(AddressAnnotation constraintAnnotation) { // initialize the zipcode/city/country correlation service } /** * Validate zipcode and city depending on the country */ public boolean isValid(Address object, ConstraintValidatorContext context) { if (!(object instanceof Address)) { throw new IllegalArgumentException("@Address only applies to Address"); } Address address = (Address) object; Country country = address.getCountry(); if (country.getISO2() == "FR") { // check address.getZipCode() structure for France (5 numbers) // check zipcode and city correlation (calling an external service?) return isValid; } else if (country.getISO2() == "GR") { // check address.getZipCode() structure for Greece // no zipcode / city correlation available at the moment return isValid; } // ... } }
高级地址验证规则 被遗忘在地址之外 对象并实现
MultiCountryAddressValidator
。通过 访问对象实例,类 等级约束有很多 灵活性,可以验证多个 相关属性。注意 排序不在等式中 在这里,我们将回到它 下一篇文章。专家组讨论了各种问题 多个属性支持 方法:我们认为班级 约束方法提供了两者 足够简单和灵活 与其他财产水平相比 涉及依赖的方法。 欢迎您的反馈。
答案 1 :(得分:24)
要与Bean Validation一起正常使用,Pascal Thivent的answer中提供的示例可以重写如下:
select
projects.name,
sum(current_date - (projects_programmers.joined_at))
from projects, projects_programmers
where projects.id = projects_programmers.project_id
group by projects.name, projects_programmers.joined_at
@ValidAddress
public class Address {
@NotNull
@Size(max = 50)
private String street1;
@Size(max = 50)
private String street2;
@NotNull
@Size(max = 10)
private String zipCode;
@NotNull
@Size(max = 20)
private String city;
@Valid
@NotNull
private Country country;
// Getters and setters
}
public class Country {
@NotNull
@Size(min = 2, max = 2)
private String iso2;
// Getters and setters
}
@Documented
@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy = { MultiCountryAddressValidator.class })
public @interface ValidAddress {
String message() default "{com.example.validation.ValidAddress.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
答案 2 :(得分:8)
当您希望继续使用Bean Validation规范时,可以使用类级别验证器。如果您乐意使用Hibernate Validator功能,可以使用Validator-4.1.0.Final中提供的 @ScriptAssert 。
答案 3 :(得分:0)
编程语言:Java
这是一个对我有帮助的解决方案。
要求:
在 UI 上有一个包含对象列表的表格,该列表具有映射到具有 fk 关系的多个表格/对象。
现在验证是在多个 fks 之外,只有 3 列无法复制。我的意思是 3 的组合不能重复。
注意:当我在 Java 上开发自定义框架时,没有使用 HashCode 或 equals 的选项。如果我将使用数组索引迭代,这将增加我不想要的时间复杂度。
解决方案:
我准备了一个 String ,它是一个自定义的 String ,包含 FK1#ID of FK2#ID of FK3 例如:字符串的形式如下 -> 1000L#3000L#1300L#
这个字符串,我们将使用 set 的 add() 添加到一个集合中,如果出现重复,它将返回 false。
基于这个标志,我们可以抛出验证消息。
这对我有帮助。 DS 可能无济于事。