Hibernate項(xiàng)目中不僅有ORM一個(gè)框架辟宗,這里介紹的是它的另一個(gè)框架Validator停撞,用來(lái)驗(yàn)證實(shí)體類(lèi)是否滿足需求赖欣。Validator實(shí)現(xiàn)了Java的一項(xiàng)標(biāo)準(zhǔn)Bean Validation邻悬。
如果使用Maven佩脊,就需要在pom.xml中添加如下一段蛙粘,Hibernate需要Java EL表達(dá)式,因此需要添加EL的依賴(lài)項(xiàng)威彰。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.4.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
如果使用Gradle出牧,需要將上面的依賴(lài)項(xiàng)轉(zhuǎn)換一下。
compile group: 'org.hibernate', name: 'hibernate-validator', version: '5.3.4.Final'
compile group: 'javax.el', name: 'javax.el-api', version: '3.0.1-b04'
compile group: 'org.glassfish.web', name: 'javax.el', version: '2.2.6'
添加依賴(lài)之后歇盼,就可以在實(shí)體類(lèi)中添加條件注解了舔痕。常用的幾個(gè)注解如下:
注解 | 作用 |
---|---|
AssertTrue | 布爾值為真 |
AssertFalse | 布爾值為假 |
Null | 引用為空 |
NotNull | 引用不為空 |
NotEmpty | 字符串引用和值都不是空 |
Min | 數(shù)字的最小值 |
Max | 數(shù)字的最大值 |
Past | 日期必須是過(guò)去 |
Future | 日期必須是未來(lái) |
Pattern | 字符串必須匹配正則表達(dá)式 |
Valid | 遞歸驗(yàn)證引用 |
Size | 驗(yàn)證字符串是否在Size范圍內(nèi) |
驗(yàn)證字符串是否是一個(gè)有效的電子郵箱 | |
URL | 字符串是否是一個(gè)有效的URL |
需要注意最后兩個(gè)注解是Hibernate Validator自定義的,假如使用其他的Bean Validation實(shí)現(xiàn),可能沒(méi)有這兩個(gè)注解伯复。
下面向兩個(gè)實(shí)體類(lèi)添加了驗(yàn)證注解慨代,其他方法已經(jīng)省略了。和JPA注解一樣啸如,如果驗(yàn)證注解添加到字段上侍匙,Hibernate就會(huì)直接讀取字段的值。如果注解到Getter方法上叮雳,Hibernate就會(huì)調(diào)用方法取得值想暗。在一個(gè)類(lèi)中不要同時(shí)應(yīng)用這兩種方式,會(huì)導(dǎo)致重復(fù)驗(yàn)證的問(wèn)題帘不。如果在一個(gè)集合上應(yīng)用Valid注解说莫, Hibernate就會(huì)遞歸驗(yàn)證集合中的每一個(gè)元素。
public class Author {
@NotNull
@Size(min = 6, max = 15)
@Pattern(regexp = "([a-zA-Z]+\d*)+")
private String username;
@NotNull
@Size(min = 6, max = 20)
private String password;
@NotNull
private String nickname;
@Email
private String email;
@Min(0)
private int age;
@Size(max = 500)
private String address;
@Past
@NotNull
private Date birthday;
@Valid
@NotNull
private List<Article> articles = new ArrayList<>();
}
public class Article {
@NotNull
private String title;
@NotNull
private String content;
@NotNull
private Author author;
@Past
private Date createTime;
@Past
private Date modifyTime;
}
向?qū)嶓w類(lèi)添加了驗(yàn)證注解之后厌均,我們就可以開(kāi)始驗(yàn)證了唬滑。首先需要構(gòu)造一個(gè)ValidatorFactory,然后使用構(gòu)造出的ValidatorFactory生成一個(gè)Validator棺弊,然后調(diào)用這個(gè)Validator的validate方法晶密,就可以驗(yàn)證實(shí)體類(lèi)了。validate方法會(huì)返回一個(gè)Set<ConstraintViolation>模她,每一個(gè)ConstraintViolation都是一個(gè)驗(yàn)證結(jié)果稻艰,如果實(shí)體類(lèi)沒(méi)有錯(cuò)誤,那么這個(gè)集合的大小就是0侈净,表示驗(yàn)證通過(guò)尊勿。如果存在錯(cuò)誤,我們就可以通過(guò)這個(gè)集合來(lái)查看存在什么錯(cuò)誤畜侦。
public class ValidatorTest {
private static ValidatorFactory factory;
private static Validator validator;
private static Logger logger;
@BeforeClass
public static void init() {
factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
logger = LoggerFactory.getLogger(ValidatorTest.class);
}
@AfterClass
public static void clean() {
factory.close();
}
@Test
public void testKindsOfErrors() {
Author author = new Author();
author.setUsername("123");
author.setPassword("1234");
author.setAddress("");
author.setEmail("");
author.setArticles(null);
author.setAge(-20);
Set<ConstraintViolation<Author>> set = validator.validate(author);
for (ConstraintViolation<Author> c : set) {
logger.info(c.toString());
}
}
@Test
public void testAllRight() {
Author author = new Author();
author.setUsername("yitian");
author.setPassword("12345678");
author.setAddress("");
author.setNickname("");
author.setEmail("yitian@yitian.com");
author.setBirthday(new Date());
Set<ConstraintViolation<Author>> set = validator.validate(author);
for (ConstraintViolation<Author> c : set) {
logger.info(c.toString());
}
Assert.assertEquals(0, set.size());
}
@Test
public void testOneProperty() {
Author author = new Author();
author.setUsername("yitian");
Set<ConstraintViolation<Author>> set = validator.validateProperty(author, "username");
for (ConstraintViolation<Author> c : set) {
logger.info(c.toString());
}
}
@Test
public void testCustomMessage() {
Article article = new Article();
LocalDate date = LocalDate.of(2099, 1, 1);
article.setModifyTime(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
Set<ConstraintViolation<Article>> set = validator.validateProperty(article, "modifyTime");
for (ConstraintViolation<Article> c : set) {
logger.info(c.toString());
}
}
}
以上就是一個(gè)簡(jiǎn)單的驗(yàn)證的例子元扔。通過(guò)這個(gè)例子,大家應(yīng)該明白了Hibernate Validator的基本內(nèi)容旋膳。很多框架比如Spring也提供了相關(guān)的內(nèi)容澎语,能方便的將Hibernate Validator整合到項(xiàng)目中。如果希望了解更多信息验懊,可以查看一下它們的相關(guān)文檔擅羞。這里就起到一個(gè)拋磚引玉的作用。