搜索词>>hibernate validate 耗时0.0020
  • hibernate validate 手动验证集合/验证树形类结构

    提示:文末提供demo项目下载!!!一、hibernate validate项目创建​ 二、hibernate validate依赖说明$title(pom.xml) <?xml version="1.0" encoding="UTF-8"提示:文末提供demo项目下载!!!一、hibernate validate项目创建​ 二、hibernate validate依赖说明$title(pom.xml) <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo-manual-validate</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo-manual-validate</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 重点配置: <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.16.Final</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.el</artifactId> <version>2.2.4</version> </dependency>三、hibernate validate验证工具编写$title(ValidateUtils.java) package com.example.demomanualvalidate.util; import org.springframework.util.StringUtils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; import java.util.Set; public class ValidateUtils { public static String validate(Object obj) { // 用于存储验证后的错误信息 StringBuffer buffer = new StringBuffer(64); Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); if (obj!=null&& obj instanceof Collection){ Collection collection=(Collection)obj; for (Object ob:collection){ String res=validate(ob); if (!StringUtils.isEmpty(res)){ buffer.append(res); buffer.append(","); } } } //对象字段中含有集合的处理 Field[] fields = obj.getClass().getDeclaredFields(); for (Field field:fields){ field.setAccessible(true); Object fv=getFieldValueByName(field.getName(),obj); if (fv!=null&&fv instanceof Collection){ String res=validate(fv); if (!StringUtils.isEmpty(res)){ buffer.append(res); buffer.append(","); } } } // 验证某个对象,其实也可以只验证其中的某一个属性的 Set<ConstraintViolation<Object>> constraintViolations = validator.validate(obj); Iterator<ConstraintViolation<Object>> iter = constraintViolations.iterator(); while (iter.hasNext()) { String message = iter.next().getMessage()+","; buffer.append(message); } if(buffer.length()>0) return buffer.toString().substring(0, buffer.toString().length()-1); return buffer.toString(); } /** * 根据属性名获取属性值 * */ public static Object getFieldValueByName(String fieldName, Object o) { try { String firstLetter = fieldName.substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + fieldName.substring(1); Method method = o.getClass().getMethod(getter, new Class[] {}); Object value = method.invoke(o, new Object[] {}); return value; } catch (NoSuchMethodException e){ // System.out.println("验证字段get方法未找到"); return null; } catch (InvocationTargetException e) { //忽略方法内部错误 return null; } catch (Exception e) { throw new RuntimeException("验证过程获取属性值错误",e); } } } 四、hibernate validate验证数据模型创建$title(DogFood.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotEmpty; /** * 狗粮 */ public class DogFood { @NotEmpty(message = "狗粮名称不能为空") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } $title(Dog.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotNull; import java.util.List; public class Dog { public Dog(String name) { this.name = name; } @NotNull(message = "宠物名称不能为空") private String name; private List<DogFood> foods; public List<DogFood> getFoods() { return foods; } public void setFoods(List<DogFood> foods) { this.foods = foods; } public String getName() { return name; } public void setName(String name) { this.name = name; } }  $title(Persion.java) package com.example.demomanualvalidate.model; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; public class Persion { public Persion(String name, List<Dog> dogs) { this.name = name; this.dogs = dogs; } @NotEmpty(message = "用户名不能为空") private String name; @NotNull(message = "必须有宠物狗") private List<Dog> dogs;//拥有的宠物狗 public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Dog> getDogs() { return dogs; } public void setDogs(List<Dog> dogs) { this.dogs = dogs; } } 五、hibernate validate验证测试$title(Test.java) package com.example.demomanualvalidate; import com.example.demomanualvalidate.model.Dog; import com.example.demomanualvalidate.model.DogFood; import com.example.demomanualvalidate.model.Persion; import com.example.demomanualvalidate.util.ValidateUtils; import java.util.Arrays; public class Test { public static void main(String[] args) { //-----0 Persion p0=new Persion("", null); String failValue=ValidateUtils.validate(p0); System.out.println("错误信息0:"+failValue); Dog d1=new Dog(null); Persion p1=new Persion("", Arrays.asList(new Dog[]{d1})); failValue=ValidateUtils.validate(p1); System.out.println("错误信息1:"+failValue); //-----2 DogFood df=new DogFood(); d1.setFoods(Arrays.asList(new DogFood[]{df})); Persion p2=new Persion("", Arrays.asList(new Dog[]{d1})); failValue=ValidateUtils.validate(p2); System.out.println("错误信息2:"+failValue); //---GOOD Dog d=new Dog("阿三"); Persion p=new Persion("小左",Arrays.asList(new Dog[]{d})); failValue=ValidateUtils.validate(p); System.out.println("错误信息:"+failValue); } } 执行结果截图:​从输出结果来看,已经实现了hibernate validate树形验证,有任何问题欢迎下方评论区留言讨论。 项目下载地址 :demo-manual-validate.zip
  • Spring Boot validation整合hibernate validator实现数据验证

    Spring Boot validation整合hibernate validator实现数据验证,Spring Boot validation使用说明,Spring Boot validation使用教程<h2>引言</h2>     这里主要讲解在Spring  Boot项目中整合hibernate validator框架实现Spring  Boot项目的validation 验证机制。方便后端验证前端或者接口传递过来的数据格式是否正确。 <h2>一.准备环境</h2> <ul> <li>jdk1.8+(Spring Boot项目推荐使用1.8)</li> <li>eclipse(或者你喜欢的IDE)</li> <li>maven 3+</li> </ul> <h2>二.编码实现Spring Boot validation</h2> <h3>2.1创建一个spring boot项目并添web模块和validation模块</h3> 项目结构图如下:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot项目结果图" src="/assist/images/blog/017be0b2e4e848cb9bc98279929d073a.png" /><br /> 项目的依赖文件: <pre> <code class="language-xml"><?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.xqlee.project.demo</groupId> <artifactId>demo-springboot-hibernate-validator</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demo-springboot-hibernate-validator</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter- </artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> </code></pre> <h3> </h3> <blockquote> <h3>注意:</h3> <pre> <code class="language-xml"> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency></code></pre> 该模块会自动加载hibernate-validation依赖。不要自己手动配置谨防依赖问题</blockquote> <h3><br /> 2.2编写一个测试的简单对象POJO</h3> <pre> <code class="language-java">package net.xqlee.project.demo.pojo; import javax.validation.constraints.Pattern; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.Range; public class User { @NotBlank(message = "用户名称不能为空。") private String name; @Range(max = 150, min = 1, message = "年龄范围应该在1-150内。") private Integer age; @NotEmpty(message = "密码不能为空") @Length(min = 6, max = 8, message = "密码长度为6-8位。") @Pattern(regexp = "[a-zA-Z]*", message = "密码不合法") private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } </code></pre> 细心的朋友可能已经发现一些属性上的注解。验证框架正是实现了这些注解的具体验证。hibernate在java的JSR-303标准上还添加了一些额外的验证注解实现。这些实现都为我们后端验证数据取得了巨大的方便。 <blockquote> <p>提示:<br /> 验证注解推荐使用</p> <p>javax.validation.constraints包下的注解,不要使用hibernate的<br /> 在2.0中hibernate的很多注解已经弃用,但是</p> <p>javax.validation.constraints包下的注解增多增强<br /> 一种规范性的趋势</p> </blockquote> <h3>2.3编写一个controller用于测试验证机制</h3> <pre> <code class="language-java">package net.xqlee.project.demo.controller; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import net.xqlee.project.demo.pojo.User; @RestController public class ValidatorController { private static final Logger log = LoggerFactory.getLogger(ValidatorController.class); /** * 验证框架使用测试 * * @param user * @param result */ @PostMapping("v/t1.json") public void v1(@Validated User user, BindingResult result) { StringBuilder sBuilder = new StringBuilder(); sBuilder.append("\n"); if (result.hasErrors()) { List<ObjectError> list = result.getAllErrors(); for (ObjectError error : list) { log.info(error.getCode() + "---" + error.getArguments() + "---" + error.getDefaultMessage()); sBuilder.append(error.getDefaultMessage()); sBuilder.append("\n"); } } log.info(sBuilder.toString()); } } </code></pre> <blockquote> <p>提示:<br /> @Validated (org.springframework.validation.annotation)<br /> 或者@Valid(javax.validation)<br /> 验证注解推荐写在方法的参数列表中,例如:<br /> Object   methodName(@Valid Object params){...}<br /> Object   methodName(@Validated Object params){...}<br /> <br />  </p> </blockquote> <h2><br /> 三.演示</h2> <h3>3.1启动spring boot项目</h3> <h3>3.2通过工具postmain进行提交数据验证</h3> <strong>第一组测试:</strong><br /> <br /> 提交全部为空数据:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据1" src="/assist/images/blog/8d1b26436c0f42b382e4aa7378e4c466.png" /><br /> 观察eclipse的控制台输出:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出1" src="/assist/images/blog/6b5e924b8c57446ab125be2043cec0e3.png" /><br /> 可以看到非空验证已经实现。<br /> <br /> <strong>第二组测试:</strong><br /> <br /> 接下来输入一个非空的名称和密码<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据2" src="/assist/images/blog/d86badcd7bc44cdba5080e8f87406023.png" /><br /> 观察eclipse控制台:<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出2" src="/assist/images/blog/87f994b3a6eb4bf9a77f3ce652471c11.png" /><br /> 可以看到名称的验证错误信息已经没有说明已经输入正确。但是密码却没有通过正则表达式的验证所以报错不合法,在对象上我们设置的密码只能是大写的字母。所以刚才输入的全数字不合法。<br /> <br /> <strong>第三组测试:</strong><br /> <br /> 接下来输入正常的密码<br /> <img srcset="" width="" size="" class="img-thumbnail" alt="spring boot validation测试数据3" src="/assist/images/blog/40be7f44b6144ade956b3453ae420766.png" />观察控制台:<br /> <br /> <img srcset="" width="" size="" class="img-thumbnail" alt="Spring Boot validation 控制台输出3" src="/assist/images/blog/2be73b7acb544f22845efacbb9c58a6f.png" /><br /> 可以看到已经没有错误信息。验证通过
  • Spring Boot 2.0 hibernate validate List 验证

    Spring Boot 2.0 hibernate validate List 验证Spring Boot 2.0 hibernate validate List 验证
  • hibernate validator 正则表达式报错javax.validation.constraints.Pattern

    hibernate validator 正则表达式报错HV000030: No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'java.lang.Integer'.HV000030: No validator could be found for constraint 'javax.validation.constraints.Pattern' validating type 'java.lang.Integer'.
  • Spring Boot 2.0 hibernate validate 版本冲突导致严重失效

    Spring Boot 2.0 hibernate validate 版本冲突导致验证无效,HV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.String'. Check configuration forHV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.String'. Check configuration for 'parameter.applyNo'"
  • spring boot 2.3 hibernate validate框架未引入

    项目升级到springboot之后,参数校验的注解报错,经过与原项目对比,发现spring-boot-starter-web的依赖项已经去除了依赖原版会有如下: <dependency>l; <groupId>l;org.hiberna项目升级到springboot之后,参数校验的注解报错,经过与原项目对比,发现spring-boot-starter-web的依赖项已经去除了依赖原版会有如下: <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.17.Final</version> <scope>compile</scope> </dependency>2.3中已经删除了解决方法手动引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>官网说明链接:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#validation-starter-no-longer-included-in-web-starters
  • Spring 5 MVC 整合 Hibernate 5

    在这个Spring5教程中,学习创建Spring 5 MVC Web应用程序,处理表单提交,集成hibernate连接到后端数据库,以及添加用于输入表单字段验证的hibernate验证器。<h2>引言</h2>     在这个Spring5教程中,学习创建Spring 5 MVC Web应用程序,处理表单提交,集成hibernate连接到后端数据库,以及添加用于输入表单字段验证的hibernate验证器。<br /> <br />     我们将创建一个简单的屏幕,我们可以添加用户字段(名称和电子邮件)。 这些细节将首先验证,然后使用休眠存储在HSQL数据库中。 该页面也将列出所有存储的用户。 <h2>一.Spring MVC 5整合hibernate5开发环境准备</h2> <ul> <li>Eclipse Neon.2 +</li> <li>JDK 1.8 +</li> <li>Spring 5.0.0.RELEASE</li> <li>Hibernate 5.2.11.Final</li> <li>Hibernate validator 5.4.1.Final</li> <li>Servlets 3.1.0</li> <li>HSQLDB 1.8.0.10</li> <li>Tomcat 7 maven plugin 2.2</li> </ul> <h2>二.Spring MVC 5整合hibernate5项目结构图</h2> 该项目具有典型的Maven Web应用程序结构。<br /> <img alt="Spring5" class="img-thumbnail" src="/assist/images/blog/2cd6c348063d40caabff4dfdc8e79010.png" /> <h2>三.Spring MVC 5整合hibernate5类图关系</h2> <img alt="" class="img-thumbnail" src="/assist/images/blog/3bb67013c0b84472824f0936c8f82b6e.png" /> <h2>四.Spring MVC 5整合hibernate5 maven依赖</h2> 查找用于在pom.xml文件中运行此示例的项目依赖项。 <pre> <code class="language-xml"><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.howtodoinjava.spring5.demo</groupId> <artifactId>spring5-mvc-hibernate-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.0.0.RELEASE</spring.version> <hibernate.version>5.2.11.Final</hibernate.version> <hibernate.validator>5.4.1.Final</hibernate.validator> <c3p0.version>0.9.5.2</c3p0.version> <jstl.version>1.2.1</jstl.version> <tld.version>1.1.2</tld.version> <servlets.version>3.1.0</servlets.version> <jsp.version>2.3.1</jsp.version> <hsqldb.version>1.8.0.10</hsqldb.version> </properties> <dependencies> <!-- Spring MVC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <!-- Hibernate Core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Hibernate-C3P0 Integration --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>${hibernate.version}</version> </dependency> <!-- c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <!-- Hibernate Validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate.validator}</version> </dependency> <!-- JSTL Dependency --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>${tld.version}</version> </dependency> <!-- Servlet Dependency --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlets.version}</version> <scope>provided</scope> </dependency> <!-- JSP Dependency --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- HSQL Dependency --> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>${hsqldb.version}</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/java</sourceDirectory> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> </configuration> </plugin> </plugins> </build> </project></code></pre> <h2>五.配置Spring MVC 5 servlet分发器DispatcherServlet</h2>     随着Servlet 3.0规范的发布,可以用几乎没有xml来配置你的Servlet容器。 为此,Servlet规范中有ServletContainerInitializer。 在这个类中,你可以注册过滤器,监听器,servlet等,就像你在web.xml中一样。<br /> <br />     Spring提供了知道如何处理WebApplicationInitializer类的SpringServletContainerInitializer。 AbstractAnnotationConfigDispatcherServletInitializer类实现了内部实现WebApplicationInitializer的WebMvcConfigurer。 它注册一个ContextLoaderlistener(可选)和DispatcherServlet,并允许您轻松添加配置类来加载这两个类,并将过滤器应用于DispatcherServlet并提供servlet映射。<br />   <pre> <code class="language-java">public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { HibernateConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }</code></pre> <h2>六.Spring Web MVC 5 配置</h2> Spring Web MVC配置如下。 <pre> <code class="language-java">import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.howtodoinjava.demo.spring"}) public class WebMvcConfig implements WebMvcConfigurer { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource source = new ResourceBundleMessageSource(); source.setBasename("messages"); return source; } @Override public Validator getValidator() { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); validator.setValidationMessageSource(messageSource()); return validator; } }</code></pre> <ol> <li><code>WebMvcConfigurer</code> 定义了通过使用@EnableWebMvc自定义或添加到默认的<code>@EnableWebMvc</code>配置的选项。</li> <li><code>@EnableWebMvc</code> 启用默认的Spring MVC配置,并注册DispatcherServlet所期望的Spring MVC基础架构组件。</li> <li><code>@Configuration</code> 指示一个类声明了一个或多个@Bean方法,并且可以被Spring容器处理,以在运行时为这些bean生成bean定义和服务请求。</li> <li><code>@ComponentScan</code> 注释用于指定要扫描的基本包。任何用@Component和@Configuration注解的类都将被扫描。</li> <li><code>InternalResourceViewResolver</code> 有助于映射逻辑视图名称,以便在特定的预配置目录下直接查看文件。</li> <li><code>ResourceBundleMessageSource</code> 使用指定的基本名称访问资源包(这里是消息)。</li> <li><code>LocalValidatorFactoryBean</code> 引导一个<code>javax.validation.ValidationFactory</code> ,并通过Spring Validator接口以及JSR-303 Validator接口和<code>ValidatorFactory</code> 接口本身公开它。</li> </ol> <h2>七.Hibernate 配置</h2> 在例子中使用Hibernate配置。 <pre> <code class="language-java">import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScans; import org.springframework.context.annotation.Configuration; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import com.howtodoinjava.demo.spring.model.User; @Configuration @EnableTransactionManagement public class HibernateConfig { @Autowired private ApplicationContext context; @Bean public LocalSessionFactoryBean getSessionFactory() { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml")); factoryBean.setAnnotatedClasses(User.class); return factoryBean; } @Bean public HibernateTransactionManager getTransactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(getSessionFactory().getObject()); return transactionManager; } }</code></pre> <ul> <li><code>LocalSessionFactoryBean</code> 创建一个Hibernate <code>SessionFactory</code>. 这是在Spring应用程序上下文中设置共享Hibernate SessionFactory的常用方法。</li> <li><code>EnableTransactionManagement</code> 支持Spring的注解驱动事务管理功能。</li> <li><code>HibernateTransactionManager</code> 将Hibernate Session从指定的工厂绑定到线程,可能允许每个工厂有一个线程绑定的Session。 此事务管理器适用于使用单个Hibernate</li> <li><code>SessionFactory</code> 进行事务性数据访问的应用程序,但也支持事务内的直接<code>DataSource</code> 访问,即普通JDBC。</li> </ul> <strong>hibernate.cfg.xml:</strong> <pre> <code class="language-xml"><?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.archive.autodetection">class,hbm</property> <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.url">jdbc:hsqldb:mem:howtodoinjava</property> <property name="hibernate.hbm2ddl.auto">create</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.acquire_increment">1800</property> <property name="hibernate.c3p0.max_statements">150</property> </session-factory> </hibernate-configuration></code></pre> <h2>八.Spring Controller and Path Mappings</h2> 控制器类有两个简单的GET和POST操作映射。 如果输入字段未被验证,则返回相同的表单bean以显示错误消息。 否则返回刷新视图。 <pre> <code class="language-java"> import java.util.Locale; import javax.validation.alid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.howtodoinjava.demo.spring.model.User; import com.howtodoinjava.demo.spring.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @GetMapping("/") public String userForm(Locale locale, Model model) { model.addAttribute("users", userService.list()); return "editUsers"; } @ModelAttribute("user") public User formBackingObject() { return new User(); } @PostMapping("/addUser") public String saveUser(@ModelAttribute("user") @Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("users", userService.list()); return "editUsers"; } userService.save(user); return "redirect:/"; } }</code></pre> <h2>九.Service and DAO 层</h2> 服务和DAO层是用@Service和@Repository注释标注的普通服务组件。 @交易注解应用于服务层以支持事务处理。<br /> <br /> <code>UserService</code> and <code>UserServiceImpl</code><br />   <pre> <code class="language-java">public interface UserService { void save(User user); List<User> list(); } @Service public class UserServiceImp implements UserService { @Autowired private UserDao userDao; @Transactional public void save(User user) { userDao.save(user); } @Transactional(readOnly = true) public List<User> list() { return userDao.list(); } }</code></pre> <code>UserDao</code> and <code>UserDaoImp</code><br />   <pre> <code class="language-java">public interface UserDao { void save(User user); List<User> list(); } @Repository public class UserDaoImp implements UserDao { @Autowired private SessionFactory sessionFactory; @Override public void save(User user) { sessionFactory.getCurrentSession().save(user); } @Override public List<User> list() { @SuppressWarnings("unchecked") TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery("from User"); return query.getResultList(); } }</code></pre> User<br />   <pre> <code class="language-java">import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; @Entity @Table(name = "TBL_USERS") public class User { @Id @GeneratedValue @Column(name = "USER_ID") private Long id; @Column(name = "USER_NAME") @Size(max = 20, min = 3, message = "{user.name.invalid}") @NotEmpty(message="Please Enter your name") private String name; @Column(name = "USER_EMAIL", unique = true) @Email(message = "{user.email.invalid}") @NotEmpty(message="Please Enter your email") private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }</code></pre> <h2>十.页面和消息</h2> 最后,使用JSP文件和消息资源包<br /> <br /> editUsers.jsp<br />   <pre> <code class="language-html"><%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring5 MVC Hibernate Demo</title> <style type="text/css"> .error { color: red; } table { width: 50%; border-collapse: collapse; border-spacing: 0px; } table td { border: 1px solid #565454; padding: 20px; } </style> </head> <body> <h1>Input Form</h1> <form:form action="addUser" method="post" modelAttribute="user"> <table> <tr> <td>Name</td> <td> <form:input path="name" /> <br /> <form:errors path="name" cssClass="error" /> </td> </tr> <tr> <td>Email</td> <td> <form:input path="email" /> <br /> <form:errors path="email" cssClass="error" /> </td> </tr> <tr> <td colspan="2"><button type="submit">Submit</button></td> </tr> </table> </form:form> <h2>Users List</h2> <table> <tr> <td><strong>Name</strong></td> <td><strong>Email</strong></td> </tr> <c:forEach items="${users}" var="user"> <tr> <td>${user.name}</td> <td>${user.email}</td> </tr> </c:forEach> </table> </body> </html></code></pre> messages.properties<br />   <pre> <code class="language-html">user.name.invalid = Name must be between {2} and {1} characters. user.email.invalid = Please enter valid email address.</code></pre> <h2>十一.演示这个栗子</h2> 让我们使用maven tomcat7插件运行应用程序。 执行maven target:tomcat7:run。<br /> 访问URL: <code>http://localhost:8080</code><br /> Initial Screen<br /> <img alt="Initial Screen" class="img-thumbnail" src="/assist/images/blog/830164ad1b5448dab1aa39d340300c95.png" /><br /> 无效的输入验证<br /> <img alt="无效的输入验证" class="img-thumbnail" src="/assist/images/blog/8ddf9070177c4ce3a00c5dfe4b099950.png" /><br /> 有效的表格提交<br /> <img alt="有效的表格提交" class="img-thumbnail" src="/assist/images/blog/6ef29b6dbc1f4fb7954a3cb9bac38159.png" /><br /> 检查服务器日志: <pre> <code class="language-html">Hibernate: call next value for hibernate_sequence Hibernate: insert into TBL_USERS (USER_EMAIL, USER_NAME, USER_ID) values (?, ?, ?) Hibernate: select user0_.USER_ID as USER_ID1_0_, user0_.USER_EMAIL as USER_EMA2_0_, user0_.USER_NAME as USER_NAM3_0_ from TBL_USERS user0_</code></pre> <a href="https://howtodoinjava.com/wp-content/downloads/spring5-mvc-hibernate-example.zip" rel="external nofollow" target="_blank">Sourcecode Download</a>
  • Hibernate Search 入门配置及简单实用

    Hibernate Search 入门配置及简单实用,在本文中,我们将讨论Hibernate Search的基础知识,如何配置它,并且我们将实现一些简单的查询。<h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>1.概述</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本文中,我们将讨论Hibernate Search的基础知识,如何配置它,并且我们将实现一些简单的查询。</span></span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2. Hibernate搜索的基础知识</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">有些时候我们必须实现全文搜索功能,使用我们已经熟悉的工具总是优点。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们已经将Hibernate和JPA用于ORM,那么我们距离Hibernate Search只有一步之遥。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>Hibernate Search集成了Apache Lucene,这是一种用Java编写的高性能和可扩展的全文搜索引擎库</strong>。这将Lucene的强大功能与Hibernate和JPA的简单性相结合。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">简而言之,我们只需要向我们的域类添加一些额外的注释,并且<strong>该工具将处理数据库/索引同步等问题。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Hibernate Search还提供了Elasticsearch集成; 然而,由于它仍处于实验阶段,我们将在这里重点介绍Lucene。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.配置</strong></h2> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.1。Maven的依赖</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们首先需要将必要的依赖添加到我们的<em>pom.xml中</em>:</span></span></span></p> <pre> <code class="language-xml"><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.8.2.Final</version> </dependency></code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">为了简单起见,我们将使用H2作为我们的数据库:</p> <pre> <code class="language-xml"><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.196</version> </dependency></code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.2。配置</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>我们还必须指定Lucene应该存储索引的位置。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这可以通过属性  <em>hibernate.search.default.directory_provider完成</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们将选择<em>文件系统</em>,这对我们的用例来说是最直接的选择。<a href="https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-configuration-directory" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档</a>中列出了更多选项  。 对于群集应用程序来说,<em>文件系统主</em> / <em>文件系统 - 从属</em>和  <em>无限大</em>是值得注意的,其中索引必须在节点之间同步。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们还必须定义索引将存储在其中的默认基本目录:</span></span></span></p> <pre> <code class="language-html">hibernate.search.default.directory_provider = filesystem hibernate.search.default.indexBase = /data/index/default</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4.模型类</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">配置完成后,我们现在准备指定我们的模型。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>在JPA注解<em>@Entity</em>和<em>@Table</em>之上,我们必须添加  <em>@Indexed</em>注释。</strong>它告诉Hibernate Search实体<em>产品</em>将被索引。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>之后,我们必须通过添加<em>@Field</em>注释来将所需的属性定义为可搜索的</strong>:</span></span></span></p> <pre> <code class="language-java">@Entity @Indexed @Table(name = "product") public class Product { @Id private int id; @Field(termVector = TermVector.YES) private String productName; @Field(termVector = TermVector.YES) private String description; @Field private int memory; // getters, setters, and constructors }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">该<em>termVector = TermVector.YES</em>  属性将需要“更多类似这样的”查询后。<br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>5.构建Lucene索引</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在开始实际查询之前,<strong>我们必须首先触发Lucene建立索引</strong>:</span></span></span></p> <pre> <code class="language-java">FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); fullTextEntityManager.createIndexer().startAndWait();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>在初始构建之后,Hibernate Search会负责保持索引是最新的</strong>。I. e。我们可以像往常一样通过<em>EntityManager</em>创建,操作和删除实体。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:<strong>我们必须确保实体完全致力于数据库,然后才能被Lucene发现并编入索引</strong>(顺便说一下,这也是为什么我们的<a href="https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-hibernate-5" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">示例代码测试用例中</a>的初始测试数据导入来自专用的JUnit测试用例,用<em>@Commit</em>注解)。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.构建和执行查询</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">现在,我们准备创建我们的第一个查询。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在下一节中,<strong>我们将展示准备和执行查询的一般工作流程。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">之后,我们将为最重要的查询类型创建一些示例查询。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.1。用于创建和执行查询的一般工作流程</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>一般来说准备和执行查询由四个步骤组成</strong>:</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在第1步中,我们必须得到一个JPA <em>FullTextEntityManager,</em>并从中获得一个<em>QueryBuilder</em>:</span></span></span></p> <pre> <code class="language-java">FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory() .buildQueryBuilder() .forEntity(Product.class) .get(); 在第2步中,我们将通过Hibernate查</code></pre> 在第2步中,我们将通过Hibernate查询DSL创建一个Lucene查询: <pre> <code class="language-java">org.apache.lucene.search.Query query = queryBuilder .keyword() .onField("productName") .matching("iphone") .createQuery();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">在第3步中,我们将Lucene查询包装到一个Hibernate查询中:</p> <pre> <code class="language-java">org.hibernate.search.jpa.FullTextQuery jpaQuery = fullTextEntityManager.createFullTextQuery(query, Product.class);</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">最后,在第4步中,我们将执行查询:</p> <pre> <code class="language-java">List<Product> results = jpaQuery.getResultList();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><em>注意</em>:默认情况下,Lucene按照相关性排序结果。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">步骤1,3和4对于所有查询类型都是相同的。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在下文中,我们将重点关注第2步,即如何创建不同类型的查询。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.2。关键字查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">最基本的用例是<strong>搜索一个特定的单词</strong>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这就是我们在前一节中已经做过的事情:</span></span></span></p> <pre> <code class="language-java">Query keywordQuery = queryBuilder .keyword() .onField("productName") .matching("iphone") .createQuery();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这里,<em>keyword()</em>指定我们正在寻找一个特定的单词,<em>onField()</em>告诉Lucene在哪里寻找和<em>匹配()</em>寻找什么。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.3。模糊查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">模糊查询的工作方式与关键字查询相似,不同之处在于<strong>我们可以定义“模糊性”的限制</strong>,超过此<strong>限制</strong>,Lucene将接受这两个词作为匹配。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">通过<em>withEditDistanceUpTo()</em>,<strong>我们可以定义一个术语可能与另一个术语相差多少</strong>。它可以设置为0,1和2,默认值是2(<em>注意</em>:这个限制来自Lucene的实现)。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">通过  <em>withPrefixLength()</em>,我们可以定义前缀的长度,模糊性应该忽略它:</span></span></span></p> <pre> <code class="language-java">Query fuzzyQuery = queryBuilder .keyword() .fuzzy() .withEditDistanceUpTo(2) .withPrefixLength(0) .onField("productName") .matching("iPhaen") .createQuery();</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.4。通配符查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">Hibernate Search还使我们能够执行通配符查询,即查询某个单词的一部分未知。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">为此,我们可以对单个字符使用“ <em>?”</em>,对任何字符序列使用“ <em>*”</em>:</span></span></span></p> <pre> <code>Query wildcardQuery = queryBuilder .keyword() .wildcard() .onField("productName") .matching("Z*") .createQuery();</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.5。短语查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们想要搜索多个单词,我们可以使用短语查询。如果需要,我们可以使用<em>phrase()</em>和<em>withSlop()</em>来查找<strong>确切的或近似的句子</strong>。斜率因子定义了句子中允许的其他单词的数量:</span></span></span></p> <pre> <code class="language-java">Query phraseQuery = queryBuilder .phrase() .withSlop(1) .onField("description") .sentence("with wireless charging") .createQuery();</code></pre>   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.6。简单查询字符串查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">使用先前的查询类型,我们必须明确指定查询类型。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们想给用户更多的权力,我们可以使用简单的查询字符串查询:<strong>由此,他可以在运行时定义自己的查询</strong>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">支持以下查询类型:</span></span></span></p> <ul style="list-style-type:disc"> <li>布尔型(使用“+”,或使用“|”,不使用“ - ”)</li> <li>前缀(前缀*)</li> <li>短语(“某个短语”)</li> <li>优先顺序(使用括号)</li> <li>模糊(fuzy〜2)</li> <li>短语查询附近的运算符(“某个短语”〜3)</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">以下示例将结合模糊,短语和布尔查询:</span></span></span></p> <pre> <code class="language-java">Query simpleQueryStringQuery = queryBuilder .simpleQueryString() .onFields("productName", "description") .matching("Aple~2 + \"iPhone X\" + (256 | 128)") .createQuery();</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.7。范围查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>范围查询搜索</strong> <strong>给定边界之间</strong><strong>的</strong><strong>值</strong>。这可以应用于数字,日期,时间戳和字符串:</span></span></span></p> <pre> <code class="language-java">Query rangeQuery = queryBuilder .range() .onField("memory") .from(64).to(256) .createQuery();</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.8。更像此查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们最后的查询类型是“ <em>更像这个</em> ” - 查询。为此,我们提供了一个实体,<strong>Hibernate Search返回一个具有相似实体的列表</strong>,每个<strong>实体</strong>都具有相似性分数。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如前所述,在这种情况下,我们的模型类中的  <em>TermVector = TermVector.YES</em>属性是必需的:它告诉Lucene在索引期间存储每个术语的频率。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">基于此,相似性将在查询执行时计算:</span></span></span></p> <pre> <code class="language-java">Query moreLikeThisQuery = queryBuilder .moreLikeThis() .comparingField("productName").boostedTo(10f) .andField("description").boostedTo(1f) .toEntity(entity) .createQuery(); List<Object[]> results = (List<Object[]>) fullTextEntityManager .createFullTextQuery(moreLikeThisQuery, Product.class) .setProjection(ProjectionConstants.THIS, ProjectionConstants.SCORE) .getResultList();</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.9。搜索多个字段</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">到目前为止,我们只使用<em>onField()</em>创建了查询一个属性的查询。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">根据用例,<strong>我们还可以搜索两个或更多属性</strong>:</span></span></span></p> <pre> <code class="language-java">Query luceneQuery = queryBuilder .keyword() .onFields("productName", "description") .matching(text) .createQuery();</code></pre> 此外,<strong>我们可以指定要分别搜索的每个属性</strong>,例如,如果我们要为一个属性定义增强: <pre> <code class="language-java">Query moreLikeThisQuery = queryBuilder .moreLikeThis() .comparingField("productName").boostedTo(10f) .andField("description").boostedTo(1f) .toEntity(entity) .createQuery();</code></pre>   <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>6.10。结合查询</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">最后,Hibernate Search还支持使用各种策略来组合查询:</span></span></span></p> <ul style="list-style-type:disc"> <li><em>应该:</em>查询应该包含子查询的匹配元素</li> <li><em>必须:</em>查询必须包含子查询的匹配元素</li> <li><em>MUST NOT</em>:查询不得包含子查询的匹配元素</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">聚合<strong>类似于布尔逻辑的<em>AND,OR</em>和<em>NOT</em></strong><em>。</em>但是,名称不同,强调它们对相关性也有影响。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">例如,两个查询之间的<em>SHOULD</em>类似于布尔<em>OR:</em>如果其中一个查询有匹配,则返回该匹配。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">但是,如果两个查询匹配,则与只有一个查询匹配的情况相比,匹配的关联性会更高:</span></span></span></p> <pre> <code class="language-java">Query combinedQuery = queryBuilder .bool() .must(queryBuilder.keyword() .onField("productName").matching("apple") .createQuery()) .must(queryBuilder.range() .onField("memory").from(64).to(256) .createQuery()) .should(queryBuilder.phrase() .onField("description").sentence("face id") .createQuery()) .must(queryBuilder.keyword() .onField("productName").matching("samsung") .createQuery()) .not() .createQuery();</code></pre> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>7.总结</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本文中,我们讨论了Hibernate Search的基础知识,并展示了如何实现最重要的查询类型。更高级的功能可以在<a href="https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档中</a>找到 。</span></span></span></p>
  • hibernate 的@Column注解在的字段上不生效

    hibernate 的@Column注解在的字段上不生效<h2><strong>问题:</strong></h2> hibernate 的@Column注解在的字段上不生效<br />   <h2><strong>原因:</strong></h2> @Column的作用范围是根据@Id的作用范围来的,即如果@Id标签放在字段上的,那么@Column就只能作用在字段上,如果@Id放在getter方法上的,那么@Column也得放到getter上。
  • Java Bean Validation 2.0的方法约束 Java自定义验证注解

    在本文中,我们将讨论如何使用Bean Validation 2.0(JSR-380)定义和验证方法约束。在前面的文章中,我们讨论了JSR-380及其内置的注释,以及如何实现属性验证。在这里,我们将重点讨论不同类型的方法约束,例如:<h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>1.概述</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本文中,我们将讨论如何使用Bean Validation 2.0(JSR-380)定义和验证方法约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在前面的文章中(<a rel="" target="_blank"href="http://www.leftso.com/blog/389.html" rel="" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">Java Bean 基础验证</a>),我们讨论了JSR-380及其内置的注释,以及如何实现属性验证。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这里,我们将重点讨论不同类型的方法约束,例如:</span></span></span></p> <ul style="list-style-type:disc"> <li>单参数约束</li> <li>交叉<strong>复杂</strong>参数(自定义Java Bean验证注解)</li> <li>返回约束</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">另外,我们将看看如何使用Spring Validator手动和自动验证约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="font-family:raleway"><span style="background-color:#ffffff">对于以下示例,我们需要与<a rel="" target="_blank"href="http://www.leftso.com/blog/389.html" rel="" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">Java Bean验证基础中</a>完全相同的依赖关系 。</span></span><br />  </p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.方法约束声明</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,<strong>我们将首先讨论如何声明方法参数的约束和方法返回的值</strong>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如前所述,我们可以使用来自<em>javax.validation.constraints的注解</em>  ,但我们也可以指定自定义约束(例如,对于自定义约束或交叉参数约束)。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.1。单参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">定义单个参数的限制很简单。<strong>我们只需要根据需要为每个参数添加注解</strong>:</span></span></span></p> <pre> <code class="language-java">public void createReservation(@NotNull @Future LocalDate begin, @Min(1) int duration, @NotNull Customer customer) { // ... }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">同样,我们可以对构造函数使用相同的方法:</span></span></span></p> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <pre> <code class="language-java">public class Customer { public Customer(@Size(min = 5, max = 200) @NotNull String firstName, @Size(min = 5, max = 200) @NotNull String lastName) { this.firstName = firstName; this.lastName = lastName; } // properties, getters, and setters }</code></pre> </div> </div> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.2。使用交叉复杂参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在某些情况下,我们可能需要一次验证多个值,例如,两个数值比另一个大一些。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于这些场景,我们可以定义自定义跨参数约束,这可能取决于两个或更多参数。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>交叉参数约束可以被认为是等同于类级约束的方法验证</strong>。我们可以使用两者来基于多个属性来实现验证。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">让我们考虑一个简单的例子:上一节中的<em>createReservation()</em>方法的变体  接受两个<em>LocalDate</em>类型的参数<em>:</em>  开始日期和结束日期。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">因此,我们要确保<em>开始</em>是在未来,<em>结束</em>是在<em>开始</em>之后。与前面的例子不同,我们不能用单个参数约束来定义它。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">相反,我们需要一个交叉参数约束。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">与单参数约束相反,<strong>交叉参数约束在方法或构造函数中声明</strong>:</span></span></span></p> <pre> <code class="language-java">@ConsistentDateParameters public void createReservation(LocalDate begin, LocalDate end, Customer customer) { // ... }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.3。创建交叉参数约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">要实现<em>@ConsistentDateParameters</em>约束,我们需要两个步骤。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,我们需要<strong>定义约束注解</strong>:</span></span></span></p> <pre> <code class="language-java">@Constraint(validatedBy = ConsistentDateParameterValidator.class) @Target({ METHOD, CONSTRUCTOR }) @Retention(RUNTIME) @Documented public @interface ConsistentDateParameters { String message() default "End date must be after begin date and both must be in the future"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这里,这三个属性对于约束注释是强制性的:</span></span></span></p> <ol> <li><strong>message</strong><em>- </em>返回创建错误消息的默认密钥,这使我们能够使用消息插值</li> <li><strong>groups</strong>   - 允许我们为约束指定验证组</li> <li><strong>payload </strong> - 可由Bean Validation API的客户端使用,以将自定义有效载荷对象分配给约束</li> </ol> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">有关如何定义自定义约束的详细信息,请查看  <a href="https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-customconstraints" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档</a>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">之后,我们可以定义验证器类:</span></span></span></p> <pre> <code class="language-java">@SupportedValidationTarget(ValidationTarget.PARAMETERS) public class ConsistentDateParameterValidator implements ConstraintValidator<ConsistentDateParameters, Object[]> { @Override public boolean isValid( Object[] value, ConstraintValidatorContext context) { if (value[0] == null || value[1] == null) { return true; } if (!(value[0] instanceof LocalDate) || !(value[1] instanceof LocalDate)) { throw new IllegalArgumentException( "Illegal method signature, expected two parameters of type LocalDate."); } return ((LocalDate) value[0]).isAfter(LocalDate.now()) && ((LocalDate) value[0]).isBefore((LocalDate) value[1]); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">正如我们所看到的,<em>isValid() </em>方法包含实际的验证逻辑。首先,我们确保我们得到两个类型为<em>LocalDate的</em>参数<em>。</em> 之后,我们检查两者是否在未来,<em>结束</em>是在<em>开始</em>之后。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">此外,值得注意的是,很重要  <em>@SupportedValidationTarget(ValidationTarget <strong>。</strong>参数)</em>的注解  <em>ConsistentDateParameterValidator</em>类是必需的。原因是因为  <em>@ConsistentDateParameter</em>  是在方法级别上设置的,但是约束条件应该应用于方法参数(而不是方法的返回值,我们将在下一节讨论)。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:Bean验证规范建议将<em>空值</em>视为有效。如果<em>null</em>不是有效值,则应该使用<em>@NotNull</em> -annotation。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.4。返回值约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>有时我们需要验证一个对象,因为它是由方法返回的。为此,我们可以使用返回值约束。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">以下示例使用内置约束:</span></span></span></p> <pre> <code class="language-java">public class ReservationManagement { @NotNull @Size(min = 1) public List<@NotNull Customer> getAllCustomers() { return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于<em>getAllCustomers()</em>,以下约束条件适用:</span></span></span></p> <ul style="list-style-type:disc"> <li>首先,返回的列表不能为<em>空,</em>且必须至少有一个条目</li> <li>此外,该列表不能包含<em>空</em>条目</li> </ul> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.5。返回值自定义约束</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在某些情况下,我们可能还需要验证复杂的对象:</span></span></span></p> <pre> <code class="language-java">public class ReservationManagement { @ValidReservation public Reservation getReservationsById(int id) { return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在这个例子中,返回的<em>Reservation</em>  对象必须满足由<em>@ValidReservation</em>定义的约束,我们将在下面定义它。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">再次,<strong>我们首先必须定义约束注释</strong>:</span></span></span></p> <pre> <code class="language-java">@Constraint(validatedBy = ValidReservationValidator.class) @Target({ METHOD, CONSTRUCTOR }) @Retention(RUNTIME) @Documented public @interface ValidReservation { String message() default "End date must be after begin date " + "and both must be in the future, room number must be bigger than 0"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">之后,我们定义类验证器:<br />  </p> <pre> <code class="language-java">public class ValidReservationValidator implements ConstraintValidator<ValidReservation, Reservation> { @Override public boolean isValid( Reservation reservation, ConstraintValidatorContext context) { if (reservation == null) { return true; } if (!(reservation instanceof Reservation)) { throw new IllegalArgumentException("Illegal method signature, " + "expected parameter of type Reservation."); } if (reservation.getBegin() == null || reservation.getEnd() == null || reservation.getCustomer() == null) { return false; } return (reservation.getBegin().isAfter(LocalDate.now()) && reservation.getBegin().isBefore(reservation.getEnd()) && reservation.getRoom() > 0); } }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.6。在构造函数中返回值</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">由于我们之前在我们的<em>ValidReservation</em>接口中定义了  <em>METHOD</em>和<em>CONSTRUCTOR</em>作为<em>目标</em>,<strong>我们也可以注释</strong><strong><em>Reservation</em></strong><strong>的构造函数</strong><strong>来验证构造的实例</strong>:</span></span></span></p> <pre> <code class="language-java">public class Reservation { @ValidReservation public Reservation( LocalDate begin, LocalDate end, Customer customer, int room) { this.begin = begin; this.end = end; this.customer = customer; this.room = room; } // properties, getters, and setters }</code></pre> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>2.7。级联验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">最后,Bean Validation API使我们不仅可以验证单个对象,还可以使用所谓的级联验证验证对象图。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>因此,如果我们想验证复杂的对象,我们可以使用<em>@Valid</em>进行级联验证</strong>。这适用于方法参数以及返回值。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">假设我们有一个带有一些属性约束的<em>Customer</em>类:</span></span></span></p> <pre> <code class="language-java">public class Customer { @Size(min = 5, max = 200) private String firstName; @Size(min = 5, max = 200) private String lastName; // constructor, getters and setters }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">一个<em>预定</em>类可能有一个<em>客户</em>的财产,以及与约束进一步特性:</p> <pre> <code class="language-java">public class Reservation { @Valid private Customer customer; @Positive private int room; // further properties, constructor, getters and setters }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start">如果我们现在引用<em>Reservation</em>作为方法参数,<strong>我们可以强制所有属性的递归验证</strong>:<br />  </p> <pre> <code class="language-java">public void createNewCustomer(@Valid Reservation reservation) { // ... }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们可以看到,我们在两个地方使用<em>@Valid</em>:</span></span></span></p> <ul style="list-style-type:disc"> <li>在<em>保留</em>参数上:当<em>createNewCustomer()</em>被调用时,它触发<em>Reservation-</em> object 的验证</li> <li>由于我们在这里有一个嵌套的对象图,我们还必须在<em>customer- </em><em>attribute</em>上添加一个<em>@Valid</em>:因此,它会触发验证这个嵌套属性</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">这也适用于返回<em>预留</em>类型对象的方法  :</span></span></span></p> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <pre> <code class="language-java">@Valid public Reservation getReservationById(int id) { return null; }</code></pre> </div> </div> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.验证方法约束</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在上一节中声明约束之后,我们现在可以继续实际验证这些约束。为此,我们有多种方法。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.1。使用Spring自动验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>Spring Validation提供了与Hibernate Validator的集成。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">注意:Spring验证基于AOP,并使用Spring AOP作为默认实现。因此,验证只适用于方法,但不适用于构造函数。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们现在希望Spring自动验证我们的约束,我们必须做两件事:</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>首先,我们必须使用<em>@Validated</em></strong><strong>注释应该验证的  </strong><strong><em>bean</em></strong>:</span></span></span><br />  </p> <pre> <code class="language-java">@Validated public class ReservationManagement { public void createReservation(@NotNull @Future LocalDate begin, @Min(1) int duration, @NotNull Customer customer){ // ... } @NotNull @Size(min = 1) public List<@NotNull Customer> getAllCustomers(){ return null; } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><strong>其次,我们必须提供一个<em>MethodValidationPostProcessor</em> bean:</strong></p> <pre> <code class="language-java">@Configuration @ComponentScan({ "org.baeldung.javaxval.methodvalidation.model" }) public class MethodValidationConfig { @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } }</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果违反约束,容器现在将抛出  <em>javax.validation.ConstraintViolationException</em>。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们使用Spring Boot,只要<em>hibernate-validator</em>在类路径中,容器就会为我们注册一个  <em>MethodValidationPostProcessor </em> bean  。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.2。CDI自动验证(JSR-365)</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">从版本1.1开始,Bean Validation与CDI(用于Java EE的上下文和依赖注入)协同工作。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果我们的应用程序在Java EE容器中运行,那么容器将在调用时自动验证方法约束。</span></span></span></p> <h3 style="margin-left:0px; margin-right:0px; text-align:start"><strong>3.3。程序化验证</strong></h3> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">对于  <strong>独立Java应用程序中的手动方法验证</strong>,我们可以使用  <em>javax.validation.executable.ExecutableValidator</em>接口。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们可以使用以下代码检索实例:</span></span></span></p> <pre> <code class="language-java">ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); ExecutableValidator executableValidator = factory.getValidator().forExecutables();</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">ExecutableValidator提供了四种方法:</span></span></span></p> <ul style="list-style-type:disc"> <li>用于方法验证的<em>validateParameters()</em>和<em>validateReturnValue()</em></li> <li>用于构造函数验证的<em>validateConstructorParameters()</em>和<em>validateConstructorReturnValue()</em></li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">验证我们的第一个方法<em>createReservation()</em>的参数如下所示:</span></span></span></p> <pre> <code class="language-java">ReservationManagement object = new ReservationManagement(); Method method = ReservationManagement.class .getMethod("createReservation", LocalDate.class, int.class, Customer.class); Object[] parameterValues = { LocalDate.now(), 0, null }; Set<ConstraintViolation<ReservationManagement>> violations = executableValidator.validateParameters(object, method, parameterValues);</code></pre> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff"><strong>注意:官方文档不鼓励直接从应用程序代码调用此接口,而是通过方法拦截技术(如AOP或代理)来使用它。</strong></span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">如果您有兴趣如何使用  <em>ExecutableValidator</em>接口,可以查看<a href="http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-validating-executable-constraints" rel="external nofollow" style="box-sizing:border-box; color:#63b175; text-decoration:none" target="_blank">官方文档</a>。</span></span></span></p> <h2 style="margin-left:0px; margin-right:0px; text-align:start"><strong>4。总结</strong></h2> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">在本教程中,我们快速浏览了如何使用Hibernate Validator的方法约束,同时我们还讨论了JSR-380的一些新功能。</span></span></span></p> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">首先,我们讨论了如何声明不同类型的约束:</span></span></span></p> <ul style="list-style-type:disc"> <li>单参数约束</li> <li>跨参数</li> <li>返回值约束</li> </ul> <p style="margin-left:0px; margin-right:0px; text-align:start"><span style="color:#535353"><span style="font-family:raleway"><span style="background-color:#ffffff">我们还看了如何使用Spring Validator手动和自动验证约束。</span></span></span></p>