原文: https://howtodoinjava.com/spring5/webmvc/spring5-mvc-hibernate5-example/
在本 spring 5 Hibernate 5 注解示例教程中,学习创建 Spring 5 MVC Web 应用程序,处理表单提交,集成 Hibernate 5 连接到后端数据库并为输入表单字段验证添加Hibernate 验证器。
我们将创建一个简单的屏幕,可以在其中添加用户字段(名称和电子邮件)。 这些详细信息将首先通过 Hibernate 进行验证,然后存储在 HSQL 数据库中。 该页面还将列出所有已存储的用户。
1. 开发环境
- Eclipse Neon 2
- JDK 1.8
- Spring 5.2.0.发布
- Hibernate 5.2.11.Final
- Hibernate 验证器 5.4.1.Final
- Servlet 3.1.0
- HSQLDB 1.8.0.10
- Tomcat 7 Maven 插件 2.2
2. 项目结构
该项目具有典型的 Maven Web 应用程序结构。

Spring5 WebMVC 项目结构
2.1. 类图

类图
3. Maven 依赖
在pom.xml文件中找到用于运行此示例的项目依赖项。
pom.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.2.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>
4. DispatcherServlet配置
随着 Servlet 3.0 规范的发布,可以(几乎)没有 xml 配置 Servlet 容器。 为此,Servlet 规范中有ServletContainerInitializer。 在该类中,您可以注册过滤器,监听器,servlet 等,就像您在web.xml中传统上所做的那样。
Spring 提供了SpringServletContainerInitializer,它知道如何处理WebApplicationInitializer类。 AbstractAnnotationConfigDispatcherServletInitializer类实现了WebMvcConfigurer,而该内部实现了WebApplicationInitializer。 它注册了ContextLoaderlistener(可选)和DispatcherServlet,并允许您轻松添加配置类以加载这两个类,并将过滤器应用于DispatcherServlet并提供 Servlet 映射。
AppInitializer.java
package com.howtodoinjava.demo.spring.config;public class AppInitializer extendsAbstractAnnotationConfigDispatcherServletInitializer {@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[] { HibernateConfig.class };}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[] { WebMvcConfig.class };}@Overrideprotected String[] getServletMappings() {return new String[] { "/" };}}
5. Spring WebMVC 配置
下面给出了使用注解配置的 Spring MVC 配置。
WebMvcConfig.java
package com.howtodoinjava.demo.spring.config;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 {@Beanpublic InternalResourceViewResolver resolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setViewClass(JstlView.class);resolver.setPrefix("/WEB-INF/views/");resolver.setSuffix(".jsp");return resolver;}@Beanpublic MessageSource messageSource() {ResourceBundleMessageSource source = new ResourceBundleMessageSource();source.setBasename("messages");return source;}@Overridepublic Validator getValidator() {LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();validator.setValidationMessageSource(messageSource());return validator;}}
WebMvcConfigurer定义用于自定义或添加到通过使用@EnableWebMvc启用的默认 Spring MVC 配置的选项。@EnableWebMvc启用默认的 Spring MVC 配置,并注册DispatcherServlet期望的 Spring MVC 基础结构组件。@Configuration指示一个类声明一个或多个@Bean方法,并且可以由 Spring 容器进行处理以在运行时为这些 bean 生成 bean 定义和服务请求。@ComponentScan注解用于指定要扫描的基本软件包。 任何用@Component和@Configuration注解的类都将被扫描。InternalResourceViewResolver有助于将逻辑视图名称映射为直接查看特定预配置目录下的文件。ResourceBundleMessageSource使用指定的基本名称(这里是消息)访问资源包。LocalValidatorFactoryBean运行javax.validation.ValidationFactory,并通过 SpringValidator接口以及 JSR-303Validator接口和ValidatorFactory接口本身公开它。
6. Hibernate 配置
该示例中使用的 Hibernate 配置是基于 Hibernate Java 的配置。
HibernateConfig.java
package com.howtodoinjava.demo.spring.config;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@EnableTransactionManagementpublic class HibernateConfig {@Autowiredprivate ApplicationContext context;@Beanpublic LocalSessionFactoryBean getSessionFactory() {LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml"));factoryBean.setAnnotatedClasses(User.class);return factoryBean;}@Beanpublic HibernateTransactionManager getTransactionManager() {HibernateTransactionManager transactionManager = new HibernateTransactionManager();transactionManager.setSessionFactory(getSessionFactory().getObject());return transactionManager;}}
LocalSessionFactoryBean创建一个 HibernateSessionFactory。 这是在 Spring 应用程序上下文中设置共享的 HibernateSessionFactory的常用方法。EnableTransactionManagement启用 Spring 的注解驱动的事务管理功能。HibernateTransactionManager将来自指定工厂的 Hibernate 会话绑定到线程,可能每个工厂允许一个线程绑定的Session。 该事务管理器适用于使用单个 HibernateSessionFactory进行事务数据访问的应用程序,但它也支持事务内的直接DataSource访问,即纯 JDBC。
hibernate.cfg.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>
7. Spring 控制器和 REST 映射
控制器类具有用于GET和POST操作的两个简单的 REST 映射。 如果输入字段未经验证,则返回相同的表单 bean 以显示错误消息。 否则返回刷新的视图。
UserController.java
package com.howtodoinjava.demo.spring.controller;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;@Controllerpublic class UserController {@Autowiredprivate 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:/";}}
8. 服务和 DAO 层
服务和 DAO 层是用@Service和@Repository注解注解的常规服务组件。 @Transactional注解在服务层应用,以支持事务。
UserService Interface amd Impl
public interface UserService {void save(User user);List<User> list();}@Servicepublic class UserServiceImp implements UserService {@Autowiredprivate UserDao userDao;@Transactionalpublic void save(User user) {userDao.save(user);}@Transactional(readOnly = true)public List<User> list() {return userDao.list();}}
UserDao Interface and Impl
public interface UserDao {void save(User user);List<User> list();}@Repositorypublic class UserDaoImp implements UserDao {@Autowiredprivate SessionFactory sessionFactory;@Overridepublic void save(User user) {sessionFactory.getCurrentSession().save(user);}@Overridepublic List<User> list() {@SuppressWarnings("unchecked")TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery("from User");return query.getResultList();}}
User.java
package com.howtodoinjava.demo.spring.model;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;}}
9. 视图和消息资源
最后,使用了 JSP 文件,并使用了消息资源包。
editUsers.jsp
<%@ 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>
messages.properties
user.name.invalid = Name must be between {2} and {1} characters.user.email.invalid = Please enter valid email address.
10. 演示
让我们使用 maven tomcat7 插件 运行应用程序。 执行 Maven 目标:tomcat7:run。
网址:http://localhost:8080

初始界面

无效输入的验证

有效表单的提交
检查服务器日志。
Console
Hibernate: call next value for hibernate_sequenceHibernate: 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_
我希望您能找到这个 Spring Hibernate Web 应用程序示例,以开始开发自己的应用程序。 这主要是针对初学者的,但是它将帮助您构建带有注解的任何带有 Hibernate 集成示例的 Spring MVC。
学习愉快!
