HibernateValidator第4篇:约束继承和对象图
本文主要讲解了约束的两种继承方式和对象图,也就是级联属性中的约束注解:包括引用的对象和集合中的元素。
一、约束继承
当一个类实现来了一个接口,或者是存在的 另一个类,则所有的被声明在父类中的约束注解,会以相同的方式,应用在当前子类上。为了清晰的展示约束注解,来看看下面这个例子。
被继承的父类:
public class Car { private String manufacturer; @NotNull public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } }
图中的注解为@NotNull,作用是约束getManufacturer()的返回值是非空的。下面来看继承它的子类:
public class RentalCar extends Car { private String rentalStation; @NotNull public String getRentalStation() { return rentalStation; } //... }
这里RentalCar类是Car类的子类,并且增加了属性rentalStation。
如果一个RentalCar实例被验证了,不但在rentalStation上的@NotNull注解约束会起作用,也包括在父类中的manufacturer上的注解约束。
同样的,如果Car不是一个类,而是一个接口,然后被RentalCar实现,那么Car接口中的注解约束,也会在RentalCar上起作用。
如果方法被重写的话,约束注解会被聚合在一起。所以如果RentalCar重写了父类Car中的getManufacturer()方法,那么加在这个方法上的任何注解,都会把父类中的@NotNull注解,也聚合在自己上面。
二、对象图
Bean Validation API不但允许验证单个类的实例,而且还允许完整的对象图(级联验证)。
为了达到这一目的,仅仅只是注解一个成员变量,或是属性。该成员变量或属性引用另外一个带有@Valid注解的对象。
例2.11 “级联验证”:
public class Car { @NotNull @Valid private Person driver; //... }
public class Person { @NotNull private String name; //... }
如果一个Car实例被验证,那么它引用的Person对象,同时也会被验证。
因为这个driver成员变量加上了@Valid注解,所以如果这个引用的person对象中的name成员变量是null的话,那么这个Car验证也会失败。
对象的验证是递归的,也就是说,如果一个引用被标记为级联验证,指向一个对象。而该对象本身有属性加上了@Valid注解,那么这些引用同时也会被验证引擎跟进。
这个验证引擎将会确保,没有无限死循环的级联验证。比如,两个对象相互引用。还要注意,null值在级联验证期间会被忽略。
作为约束,对象图的验证,也可以对容器元素起作用。这意味着,任何类型的容器中的元素,都可以加上@Valid注解。当父对象被验证的时候,每一个被包含的元素都会被验证。
级联验证也支持嵌套容器元素,下面看例2.12:
public class Car { private List<@NotNull @Valid Person> passengers = new ArrayList<Person>(); private Map<@Valid Part, List<@Valid Manufacturer>> partManufacturers = new HashMap<>(); //... } public class Part { @NotNull private String name; //... } public class Manufacturer { @NotNull private String name; //... }
在例2.12容器的级联验证中,当验证一个Car实例的时候,一个ConstraintViolation将会被创建:
- 如果包含在passengers list中的任何一个Person对象有一个null名字的话;
- 如果包含在map keys中的任何一个Part对象有一个null名字的话;
- 如果包含在嵌套map value中的任何一个Manufacturer对象有一个null名字的话。
在版本6之前,Hibernate validator支持级联验证对于容器元素中的子集。它实现在容器级别(例如,你需要用@Valid private List<person> 去激活级联验证Person)。</person>
在现有版本中,这将不再被推荐使用。请使用容器元素级别的@Valid注解,因为它更有表现力。
今天的讲解就到这里了,后面会讲解验证Bean的约束。