Hibernate Validator5.4.2--分组约束
来源:互联网 发布:mac运行windows 发热 编辑:程序博客网 时间:2024/05/22 00:41
5.分组约束
5.1.请求组
分组可以在验证期间限制应用一组约束。目标组作为var-arg参数传递给适当的validate方法。
看一个例子,Person类的name属性有一个@NotNull约束,由于没有为此约束指定组,因此默认为javax.validation.groups.Default组 。
package org.hibernate.validator.referenceguide.chapter05;public class Person { @NotNull private String name; public Person(String name) { this.name = name; } // getters and setters ...}
Driver类继承Person类并增加了age和hasDrivingLicense属性。司机必须年满18岁(@Min(18))并有驾驶执照(@AssertTrue),这两个约束属于组DriverChecks,它只是一个简单的标记接口。
使用接口使组的类型安全,并允许轻松重构。这也意味着组可以通过类继承相互继承。请参阅5.2.组继承章节。
package org.hibernate.validator.referenceguide.chapter05;public class Driver extends Person { @Min( value = 18, message = "You have to be 18 to drive a car", groups = DriverChecks.class ) public int age; @AssertTrue( message = "You first have to pass the driving test", groups = DriverChecks.class ) public boolean hasDrivingLicense; public Driver(String name) { super( name ); } public void passedDrivingTest(boolean b) { hasDrivingLicense = b; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
package org.hibernate.validator.referenceguide.chapter05;public interface DriverChecks {}
Car类有一些没有指定组的约束,这些是属于默认组的,还有passedVehicleInspection属性上的@AssertTrue约束是属于CarChecks组的,它指示一辆车是否通过了测试。
package org.hibernate.validator.referenceguide.chapter05;public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; @AssertTrue( message = "The car has to pass the vehicle inspection first", groups = CarChecks.class ) private boolean passedVehicleInspection; @Valid private Driver driver; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } public boolean isPassedVehicleInspection() { return passedVehicleInspection; } public void setPassedVehicleInspection(boolean passedVehicleInspection) { this.passedVehicleInspection = passedVehicleInspection; } public Driver getDriver() { return driver; } public void setDriver(Driver driver) { this.driver = driver; } // getters and setters ...}
package org.hibernate.validator.referenceguide.chapter05;public interface CarChecks {}
在这个例子中总共使用了三个不同的组:
- Person.name,Car.manufacturer,Car.licensePlate和Car.seatCount的约束都属于Default组。
- Driver.age和Driver.hasDrivingLicense约束属于DriverChecks组。
- Car.passedVehicleInspection约束属于CarChecks组。
下面的例子展示如何传递给Validator#validate()方法不同的组组合,以得到不同的验证结果。
// create a car and check that everything is ok with it.Car car = new Car( "Morris", "DD-AB-123", 2 );Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );assertEquals( 0, constraintViolations.size() );// but has it passed the vehicle inspection?constraintViolations = validator.validate( car, CarChecks.class );assertEquals( 1, constraintViolations.size() );assertEquals( "The car has to pass the vehicle inspection first", constraintViolations.iterator().next().getMessage());// let's go to the vehicle inspectioncar.setPassedVehicleInspection( true );assertEquals( 0, validator.validate( car, CarChecks.class ).size() );// now let's add a driver. He is 18, but has not passed the driving test yetDriver john = new Driver( "John Doe" );john.setAge( 18 );car.setDriver( john );constraintViolations = validator.validate( car, DriverChecks.class );assertEquals( 1, constraintViolations.size() );assertEquals( "You first have to pass the driving test", constraintViolations.iterator().next().getMessage());// ok, John passes the testjohn.passedDrivingTest( true );assertEquals( 0, validator.validate( car, DriverChecks.class ).size() );// just checking that everything is in order nowassertEquals( 0, validator.validate( car, Default.class, CarChecks.class, DriverChecks.class ).size());
该例子中的第一个validate()调用没有指定组,即使passedVehicleInspection的值是false,也没有出现验证错误,因为此约束不属于默认组。
下一个validate()调用指定组CarChecks,第一次验证错误,然后把passedVehicleInspection值设置成true,通过了验证。向car实例添加了一个Driver,该Driver实例的passedVehicleInspection为false,未能通过DriverChecks组的验证,只有在设置passedDrivingTest为true之后,才能通过DriverChecks组的验证。
最后一次validate()调用显示所有的约束都通过了所有组的验证。
5.2.组继承
使用验证组,我们需要为每个验证组调用validate()方法或者指定全部验证组。
在一些情况下,可能需要定义一个包含其他组的验证组,可以使用组继承。
下面的例子,在类SuperCar中,定义了一个RaceCarChecks组,它继承了Default组。它新增了一个safetyBelt(安全带)属性,表示比赛用车必须具有安全带。
package org.hibernate.validator.referenceguide.chapter05.groupinheritance;public class SuperCar extends Car { @AssertTrue( message = "Race car must have a safety belt", groups = RaceCarChecks.class ) private boolean safetyBelt; // getters and setters ...}
package org.hibernate.validator.referenceguide.chapter05.groupinheritance;import javax.validation.groups.Default;public interface RaceCarChecks extends Default {}
在下面的例子中,将分别验证普通汽车跟比赛用车的约束。
// create a supercar and check that it's valid as a generic CarSuperCar superCar = new SuperCar( "Morris", "DD-AB-123", 1 );assertEquals( "must be greater than or equal to 2", validator.validate( superCar ).iterator().next().getMessage() );// check that this supercar is valid as generic car and also as race carSet<ConstraintViolation<SuperCar>> constraintViolations = validator.validate( superCar, RaceCarChecks.class );assertThat( constraintViolations ).extracting( "message" ).containsOnly( "Race car must have a safety belt", "must be greater than or equal to 2");
在第一次调用validate()方法,没有指定特定的组,使用默认组。这里有一个验证错误,因为汽车必须至少有一个座位,该约束属于默认组。
在第二次调用validate()方法,指定了RaceCarChecks组,有两个验证错误,一个是关于默认组的座位约束,一个是RaceCarChecks组的安全带约束。
5.3.定义组序列
默认的,不管约束属于哪些组,验证约束是没有特定的顺序的。但是,我们可以控制约束被验证的顺序。
下面的例子,要求在检查汽车的其它状况之前首先要通过所有默认组的约束。最后,在开车之前,应该检查驾驶员约束。
要实现这样的验证顺序,只需要通过定义接口,并使用@GroupSequence注解,以定义组验证顺序。如果在这写组中有一个约束没有通过验证,那么其它组的约束都不会被验证。
定义验证组顺序:
package org.hibernate.validator.referenceguide.chapter05;import javax.validation.GroupSequence;import javax.validation.groups.Default;@GroupSequence({ Default.class, CarChecks.class, DriverChecks.class })public interface OrderedChecks {}
使用定义的组:
Car car = new Car( "Morris", "DD-AB-123", 2 );car.setPassedVehicleInspection( true );Driver john = new Driver( "John Doe" );john.setAge( 18 );john.passedDrivingTest( true );car.setDriver( john );assertEquals( 0, validator.validate( car, OrderedChecks.class ).size() );
5.4.重新定义默认的组序列
5.4.1. @GroupSequence
除了定义组顺序之外,@GroupSequence注解还允许重新定义指定类的默认组。只需在类上添加@GroupSequence注解,并在注解中指定特定的组顺序来替换Default 组。
下面的例子,RentalCar类重新定义了默认组。
package org.hibernate.validator.referenceguide.chapter05;@GroupSequence({ RentalChecks.class, CarChecks.class, RentalCar.class })public class RentalCar extends Car { @AssertFalse(message = "The car is currently rented out", groups = RentalChecks.class) private boolean rented; public RentalCar(String manufacturer, String licencePlate, int seatCount) { super( manufacturer, licencePlate, seatCount ); } public boolean isRented() { return rented; } public void setRented(boolean rented) { this.rented = rented; }}
package org.hibernate.validator.referenceguide.chapter05;public interface RentalChecks {}
通过这个定义,可以像验证默认组那样验证RentalChecks,CarChecks和RentalCar,
如下面的例子:
RentalCar rentalCar = new RentalCar( "Morris", "DD-AB-123", 2 );rentalCar.setPassedVehicleInspection( true );rentalCar.setRented( true );Set<ConstraintViolation<RentalCar>> constraintViolations = validator.validate( rentalCar );assertEquals( 1, constraintViolations.size() );assertEquals( "Wrong message", "The car is currently rented out", constraintViolations.iterator().next().getMessage());rentalCar.setRented( false );constraintViolations = validator.validate( rentalCar );assertEquals( 0, constraintViolations.size() );
5.4.2.@GroupSequenceProvider
除了通过@GroupSequence静态地重定义默认组外,Hibernate Validator还提供了一个SPI,用于根据对象状态动态地重定义默认组序列。
为此,需要实现接口DefaultGroupSequenceProvider并通过@GroupSequenceProvider注解将这个实现注册到目标类。下面的例子就动态地添加CarChecks组。
package org.hibernate.validator.referenceguide.chapter05.groupsequenceprovider;public class RentalCarGroupSequenceProvider implements DefaultGroupSequenceProvider<RentalCar> { @Override public List<Class<?>> getValidationGroups(RentalCar car) { List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>(); defaultGroupSequence.add( RentalCar.class ); if ( car != null && !car.isRented() ) { defaultGroupSequence.add( CarChecks.class ); } return defaultGroupSequence; }}
package org.hibernate.validator.referenceguide.chapter05.groupsequenceprovider;@GroupSequenceProvider(RentalCarGroupSequenceProvider.class)public class RentalCar extends Car { @AssertFalse(message = "The car is currently rented out", groups = RentalChecks.class) private boolean rented; public RentalCar(String manufacturer, String licencePlate, int seatCount) { super( manufacturer, licencePlate, seatCount ); } public boolean isRented() { return rented; } public void setRented(boolean rented) { this.rented = rented; }}
5.5.转换组
如果想验证car的相关检查和driver的检查,可以将所需的组显式传递给validate调用,但是如果想使这些验证作为Default组验证的一部分进行,可以使用@ConvertGroup,它允许在级联验证时去使用跟原来不同的组。
下面的例子中,@GroupSequence({ CarChecks.class, Car.class })重新定义Default组;@ConvertGroup(from = Default.class, to = DriverChecks.class)确保driver在级联验证期间将该Default组转换为DriverChecks组。
package org.hibernate.validator.referenceguide.chapter05.groupconversion;public class Driver { @NotNull private String name; @Min( value = 18, message = "You have to be 18 to drive a car", groups = DriverChecks.class ) public int age; @AssertTrue( message = "You first have to pass the driving test", groups = DriverChecks.class ) public boolean hasDrivingLicense; public Driver(String name) { this.name = name; } public void passedDrivingTest(boolean b) { hasDrivingLicense = b; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // getters and setters ...}
package org.hibernate.validator.referenceguide.chapter05.groupconversion;@GroupSequence({ CarChecks.class, Car.class })public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; @AssertTrue( message = "The car has to pass the vehicle inspection first", groups = CarChecks.class ) private boolean passedVehicleInspection; @Valid @ConvertGroup(from = Default.class, to = DriverChecks.class) private Driver driver; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } public boolean isPassedVehicleInspection() { return passedVehicleInspection; } public void setPassedVehicleInspection(boolean passedVehicleInspection) { this.passedVehicleInspection = passedVehicleInspection; } public Driver getDriver() { return driver; } public void setDriver(Driver driver) { this.driver = driver; } // getters and setters ...}
看下面的验证程序:
// create a car and validate. The Driver is still null and does not get validatedCar car = new Car( "VW", "USD-123", 4 );car.setPassedVehicleInspection( true );Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car );assertEquals( 0, constraintViolations.size() );// create a driver who has not passed the driving testDriver john = new Driver( "John Doe" );john.setAge( 18 );// now let's add a driver to the carcar.setDriver( john );constraintViolations = validator.validate( car );assertEquals( 1, constraintViolations.size() );assertEquals( "The driver constraint should also be validated as part of the default group", constraintViolations.iterator().next().getMessage(), "You first have to pass the driving test");
可以在使用@Valid注解时使用转换组,也就是说可以使用在方法、构造器的参数和返回值。
多个转换组使用@ConvertGroup.List定义。
不过也有一下限制:
- @ConvertGroup只能结合@Valid使用。如果没有,则抛出 ConstraintDeclarationException异常。
- 具有相同的值的同一元素上有多个转换规则是不合法的。在这种情况下,会抛出ConstraintDeclarationException异常。
- from属性不能引用组序列。在这种情况下会抛出ConstraintDeclarationException异常。
转换规则不会被递归执行。这第一个匹配的规则将会被使用,后续的规则将会被忽略。
- Hibernate Validator5.4.2--分组约束
- Hibernate Validator5.4.2--约束的错误信息
- Hibernate Validator5.4.2--创建自定义约束
- Hibernate Validator5.4.2--声明和验证bean的约束
- Hibernate Validator5.4.2--声明和验证方法约束
- Hibernate Validator5.4.2--使用XML配置
- hibernate分组查询
- hibernate分组查询
- hibernate 分组查询
- Hibernate(分组查询)
- hibernate 分组查询
- Hibernate-分组统计数据
- Hibernate唯一约束
- Hibernate HQL 分组求和查询
- hibernate criteria 分组 排序 关联
- hibernate criteria 分组 排序 关联
- Hibernate Criteria分组和聚合
- hibernate criteria 分组 排序 关联
- dedecms后台登录成功后,又返回登录界面已成功解决
- AJAX封装
- 织梦DEDECMS后台登录掉线返回
- spring的启动过程——spring和springMVC父子容器的原理
- 颜色空间RGB与HSV(HSL)的转换
- Hibernate Validator5.4.2--分组约束
- hibernate关系映射管理(一对多,多对一,一对一,多对多)
- 经典练习
- EasyPlayer播放海康大华RTSP流时RTSPClient客户端连接兼容问题的解决
- spring,hibernate,struts2三大框架的整合秘籍
- DedeCMS中MySQL修复表的两个小技巧
- hibernate常见面试题详解
- Python基础【02】———创建线程时的传参问题
- Unity优化技巧