原文: 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 应用程序结构。

Spring 5 MVC   Hibernate 5 示例 - 图1

Spring5 WebMVC 项目结构

2.1. 类图

Spring 5 MVC   Hibernate 5 示例 - 图2

类图

3. Maven 依赖

pom.xml文件中找到用于运行此示例的项目依赖项。

pom.xml

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd;
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.howtodoinjava.spring5.demo</groupId>
  5. <artifactId>spring5-mvc-hibernate-example</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>war</packaging>
  8. <properties>
  9. <failOnMissingWebXml>false</failOnMissingWebXml>
  10. <spring.version>5.2.0.RELEASE</spring.version>
  11. <hibernate.version>5.2.11.Final</hibernate.version>
  12. <hibernate.validator>5.4.1.Final</hibernate.validator>
  13. <c3p0.version>0.9.5.2</c3p0.version>
  14. <jstl.version>1.2.1</jstl.version>
  15. <tld.version>1.1.2</tld.version>
  16. <servlets.version>3.1.0</servlets.version>
  17. <jsp.version>2.3.1</jsp.version>
  18. <hsqldb.version>1.8.0.10</hsqldb.version>
  19. </properties>
  20. <dependencies>
  21. <!-- Spring MVC Dependency -->
  22. <dependency>
  23. <groupId>org.springframework</groupId>
  24. <artifactId>spring-webmvc</artifactId>
  25. <version>${spring.version}</version>
  26. </dependency>
  27. <!-- Spring ORM -->
  28. <dependency>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-orm</artifactId>
  31. <version>${spring.version}</version>
  32. </dependency>
  33. <!-- Hibernate Core -->
  34. <dependency>
  35. <groupId>org.hibernate</groupId>
  36. <artifactId>hibernate-core</artifactId>
  37. <version>${hibernate.version}</version>
  38. </dependency>
  39. <!-- Hibernate-C3P0 Integration -->
  40. <dependency>
  41. <groupId>org.hibernate</groupId>
  42. <artifactId>hibernate-c3p0</artifactId>
  43. <version>${hibernate.version}</version>
  44. </dependency>
  45. <!-- c3p0 -->
  46. <dependency>
  47. <groupId>com.mchange</groupId>
  48. <artifactId>c3p0</artifactId>
  49. <version>${c3p0.version}</version>
  50. </dependency>
  51. <!-- Hibernate Validator -->
  52. <dependency>
  53. <groupId>org.hibernate</groupId>
  54. <artifactId>hibernate-validator</artifactId>
  55. <version>${hibernate.validator}</version>
  56. </dependency>
  57. <!-- JSTL Dependency -->
  58. <dependency>
  59. <groupId>javax.servlet.jsp.jstl</groupId>
  60. <artifactId>javax.servlet.jsp.jstl-api</artifactId>
  61. <version>${jstl.version}</version>
  62. </dependency>
  63. <dependency>
  64. <groupId>taglibs</groupId>
  65. <artifactId>standard</artifactId>
  66. <version>${tld.version}</version>
  67. </dependency>
  68. <!-- Servlet Dependency -->
  69. <dependency>
  70. <groupId>javax.servlet</groupId>
  71. <artifactId>javax.servlet-api</artifactId>
  72. <version>${servlets.version}</version>
  73. <scope>provided</scope>
  74. </dependency>
  75. <!-- JSP Dependency -->
  76. <dependency>
  77. <groupId>javax.servlet.jsp</groupId>
  78. <artifactId>javax.servlet.jsp-api</artifactId>
  79. <version>${jsp.version}</version>
  80. <scope>provided</scope>
  81. </dependency>
  82. <!-- HSQL Dependency -->
  83. <dependency>
  84. <groupId>hsqldb</groupId>
  85. <artifactId>hsqldb</artifactId>
  86. <version>${hsqldb.version}</version>
  87. </dependency>
  88. </dependencies>
  89. <build>
  90. <sourceDirectory>src/main/java</sourceDirectory>
  91. <resources>
  92. <resource>
  93. <directory>src/main/resources</directory>
  94. </resource>
  95. </resources>
  96. <plugins>
  97. <plugin>
  98. <artifactId>maven-compiler-plugin</artifactId>
  99. <version>3.5.1</version>
  100. <configuration>
  101. <source>1.8</source>
  102. <target>1.8</target>
  103. </configuration>
  104. </plugin>
  105. <plugin>
  106. <groupId>org.apache.tomcat.maven</groupId>
  107. <artifactId>tomcat7-maven-plugin</artifactId>
  108. <version>2.2</version>
  109. <configuration>
  110. <path>/</path>
  111. </configuration>
  112. </plugin>
  113. </plugins>
  114. </build>
  115. </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

  1. package com.howtodoinjava.demo.spring.config;
  2. public class AppInitializer extends
  3. AbstractAnnotationConfigDispatcherServletInitializer {
  4. @Override
  5. protected Class<?>[] getRootConfigClasses() {
  6. return new Class[] { HibernateConfig.class };
  7. }
  8. @Override
  9. protected Class<?>[] getServletConfigClasses() {
  10. return new Class[] { WebMvcConfig.class };
  11. }
  12. @Override
  13. protected String[] getServletMappings() {
  14. return new String[] { "/" };
  15. }
  16. }

5. Spring WebMVC 配置

下面给出了使用注解配置的 Spring MVC 配置。

WebMvcConfig.java

  1. package com.howtodoinjava.demo.spring.config;
  2. import org.springframework.context.MessageSource;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.ComponentScan;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.context.support.ResourceBundleMessageSource;
  7. import org.springframework.validation.Validator;
  8. import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
  9. import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  10. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  11. import org.springframework.web.servlet.view.InternalResourceViewResolver;
  12. import org.springframework.web.servlet.view.JstlView;
  13. @Configuration
  14. @EnableWebMvc
  15. @ComponentScan(basePackages = { "com.howtodoinjava.demo.spring"})
  16. public class WebMvcConfig implements WebMvcConfigurer {
  17. @Bean
  18. public InternalResourceViewResolver resolver() {
  19. InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  20. resolver.setViewClass(JstlView.class);
  21. resolver.setPrefix("/WEB-INF/views/");
  22. resolver.setSuffix(".jsp");
  23. return resolver;
  24. }
  25. @Bean
  26. public MessageSource messageSource() {
  27. ResourceBundleMessageSource source = new ResourceBundleMessageSource();
  28. source.setBasename("messages");
  29. return source;
  30. }
  31. @Override
  32. public Validator getValidator() {
  33. LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
  34. validator.setValidationMessageSource(messageSource());
  35. return validator;
  36. }
  37. }
  1. WebMvcConfigurer定义用于自定义或添加到通过使用@EnableWebMvc启用的默认 Spring MVC 配置的选项。
  2. @EnableWebMvc启用默认的 Spring MVC 配置,并注册DispatcherServlet期望的 Spring MVC 基础结构组件。
  3. @Configuration指示一个类声明一个或多个@Bean方法,并且可以由 Spring 容器进行处理以在运行时为这些 bean 生成 bean 定义和服务请求。
  4. @ComponentScan注解用于指定要扫描的基本软件包。 任何用@Component@Configuration注解的类都将被扫描。
  5. InternalResourceViewResolver有助于将逻辑视图名称映射为直接查看特定预配置目录下的文件。
  6. ResourceBundleMessageSource使用指定的基本名称(这里是消息)访问资源包。
  7. LocalValidatorFactoryBean运行javax.validation.ValidationFactory,并通过 Spring Validator接口以及 JSR-303 Validator接口和ValidatorFactory接口本身公开它。

6. Hibernate 配置

该示例中使用的 Hibernate 配置是基于 Hibernate Java 的配置

HibernateConfig.java

  1. package com.howtodoinjava.demo.spring.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.ComponentScan;
  6. import org.springframework.context.annotation.ComponentScans;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.orm.hibernate5.HibernateTransactionManager;
  9. import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
  10. import org.springframework.transaction.annotation.EnableTransactionManagement;
  11. import com.howtodoinjava.demo.spring.model.User;
  12. @Configuration
  13. @EnableTransactionManagement
  14. public class HibernateConfig {
  15. @Autowired
  16. private ApplicationContext context;
  17. @Bean
  18. public LocalSessionFactoryBean getSessionFactory() {
  19. LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
  20. factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml"));
  21. factoryBean.setAnnotatedClasses(User.class);
  22. return factoryBean;
  23. }
  24. @Bean
  25. public HibernateTransactionManager getTransactionManager() {
  26. HibernateTransactionManager transactionManager = new HibernateTransactionManager();
  27. transactionManager.setSessionFactory(getSessionFactory().getObject());
  28. return transactionManager;
  29. }
  30. }
  • LocalSessionFactoryBean创建一个 HibernateSessionFactory。 这是在 Spring 应用程序上下文中设置共享的 Hibernate SessionFactory的常用方法。
  • EnableTransactionManagement启用 Spring 的注解驱动的事务管理功能。
  • HibernateTransactionManager将来自指定工厂的 Hibernate 会话绑定到线程,可能每个工厂允许一个线程绑定的Session。 该事务管理器适用于使用单个 Hibernate SessionFactory进行事务数据访问的应用程序,但它也支持事务内的直接DataSource访问,即纯 JDBC。

hibernate.cfg.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-configuration PUBLIC
  3. "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
  5. <hibernate-configuration>
  6. <session-factory>
  7. <property name="hibernate.archive.autodetection">class,hbm</property>
  8. <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
  9. <property name="hibernate.show_sql">true</property>
  10. <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
  11. <property name="hibernate.connection.username">sa</property>
  12. <property name="hibernate.connection.password"></property>
  13. <property name="hibernate.connection.url">jdbc:hsqldb:mem:howtodoinjava</property>
  14. <property name="hibernate.hbm2ddl.auto">create</property>
  15. <property name="hibernate.c3p0.min_size">5</property>
  16. <property name="hibernate.c3p0.max_size">20</property>
  17. <property name="hibernate.c3p0.acquire_increment">2</property>
  18. <property name="hibernate.c3p0.acquire_increment">1800</property>
  19. <property name="hibernate.c3p0.max_statements">150</property>
  20. </session-factory>
  21. </hibernate-configuration>

7. Spring 控制器和 REST 映射

控制器类具有用于GETPOST操作的两个简单的 REST 映射。 如果输入字段未经验证,则返回相同的表单 bean 以显示错误消息。 否则返回刷新的视图。

UserController.java

  1. package com.howtodoinjava.demo.spring.controller;
  2. import java.util.Locale;
  3. import javax.validation.alid;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.validation.BindingResult;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.ModelAttribute;
  10. import org.springframework.web.bind.annotation.PostMapping;
  11. import com.howtodoinjava.demo.spring.model.User;
  12. import com.howtodoinjava.demo.spring.service.UserService;
  13. @Controller
  14. public class UserController {
  15. @Autowired
  16. private UserService userService;
  17. @GetMapping("/")
  18. public String userForm(Locale locale, Model model) {
  19. model.addAttribute("users", userService.list());
  20. return "editUsers";
  21. }
  22. @ModelAttribute("user")
  23. public User formBackingObject() {
  24. return new User();
  25. }
  26. @PostMapping("/addUser")
  27. public String saveUser(@ModelAttribute("user") @Valid User user,
  28. BindingResult result, Model model) {
  29. if (result.hasErrors()) {
  30. model.addAttribute("users", userService.list());
  31. return "editUsers";
  32. }
  33. userService.save(user);
  34. return "redirect:/";
  35. }
  36. }

8. 服务和 DAO 层

服务和 DAO 层是用@Service@Repository注解注解的常规服务组件。 @Transactional注解在服务层应用,以支持事务。

阅读更多:@Service@Repository注解

UserService Interface amd Impl

  1. public interface UserService {
  2. void save(User user);
  3. List<User> list();
  4. }
  5. @Service
  6. public class UserServiceImp implements UserService {
  7. @Autowired
  8. private UserDao userDao;
  9. @Transactional
  10. public void save(User user) {
  11. userDao.save(user);
  12. }
  13. @Transactional(readOnly = true)
  14. public List<User> list() {
  15. return userDao.list();
  16. }
  17. }

UserDao Interface and Impl

  1. public interface UserDao {
  2. void save(User user);
  3. List<User> list();
  4. }
  5. @Repository
  6. public class UserDaoImp implements UserDao {
  7. @Autowired
  8. private SessionFactory sessionFactory;
  9. @Override
  10. public void save(User user) {
  11. sessionFactory.getCurrentSession().save(user);
  12. }
  13. @Override
  14. public List<User> list() {
  15. @SuppressWarnings("unchecked")
  16. TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery("from User");
  17. return query.getResultList();
  18. }
  19. }

User.java

  1. package com.howtodoinjava.demo.spring.model;
  2. import javax.persistence.Column;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.Id;
  6. import javax.persistence.Table;
  7. import javax.validation.constraints.Size;
  8. import org.hibernate.validator.constraints.Email;
  9. import org.hibernate.validator.constraints.NotEmpty;
  10. @Entity
  11. @Table(name = "TBL_USERS")
  12. public class User {
  13. @Id
  14. @GeneratedValue
  15. @Column(name = "USER_ID")
  16. private Long id;
  17. @Column(name = "USER_NAME")
  18. @Size(max = 20, min = 3, message = "{user.name.invalid}")
  19. @NotEmpty(message="Please Enter your name")
  20. private String name;
  21. @Column(name = "USER_EMAIL", unique = true)
  22. @Email(message = "{user.email.invalid}")
  23. @NotEmpty(message="Please Enter your email")
  24. private String email;
  25. public Long getId() {
  26. return id;
  27. }
  28. public void setId(Long id) {
  29. this.id = id;
  30. }
  31. public String getName() {
  32. return name;
  33. }
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37. public String getEmail() {
  38. return email;
  39. }
  40. public void setEmail(String email) {
  41. this.email = email;
  42. }
  43. }

9. 视图和消息资源

最后,使用了 JSP 文件,并使用了消息资源包

editUsers.jsp

  1. <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  2. pageEncoding="ISO-8859-1"%>
  3. <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
  4. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  5. <!DOCTYPE html>
  6. <html>
  7. <head>
  8. <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  9. <title>Spring5 MVC Hibernate Demo</title>
  10. <style type="text/css">
  11. .error {
  12. color: red;
  13. }
  14. table {
  15. width: 50%;
  16. border-collapse: collapse;
  17. border-spacing: 0px;
  18. }
  19. table td {
  20. border: 1px solid #565454;
  21. padding: 20px;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <h1>Input Form</h1>
  27. <form:form action="addUser" method="post" modelAttribute="user">
  28. <table>
  29. <tr>
  30. <td>Name</td>
  31. <td>
  32. <form:input path="name" /> <br />
  33. <form:errors path="name" cssClass="error" />
  34. </td>
  35. </tr>
  36. <tr>
  37. <td>Email</td>
  38. <td>
  39. <form:input path="email" /> <br />
  40. <form:errors path="email" cssClass="error" />
  41. </td>
  42. </tr>
  43. <tr>
  44. <td colspan="2"><button type="submit">Submit</button></td>
  45. </tr>
  46. </table>
  47. </form:form>
  48. <h2>Users List</h2>
  49. <table>
  50. <tr>
  51. <td><strong>Name</strong></td>
  52. <td><strong>Email</strong></td>
  53. </tr>
  54. <c:forEach items="${users}" var="user">
  55. <tr>
  56. <td>${user.name}</td>
  57. <td>${user.email}</td>
  58. </tr>
  59. </c:forEach>
  60. </table>
  61. </body>
  62. </html>

messages.properties

  1. user.name.invalid = Name must be between {2} and {1} characters.
  2. user.email.invalid = Please enter valid email address.

10. 演示

让我们使用 maven tomcat7 插件 运行应用程序。 执行 Maven 目标:tomcat7:run

网址:http://localhost:8080

Spring 5 MVC   Hibernate 5 示例 - 图3

初始界面

Spring 5 MVC   Hibernate 5 示例 - 图4

无效输入的验证

Spring 5 MVC   Hibernate 5 示例 - 图5

有效表单的提交

检查服务器日志。

Console

  1. Hibernate: call next value for hibernate_sequence
  2. Hibernate: insert into TBL_USERS (USER_EMAIL, USER_NAME, USER_ID) values (?, ?, ?)
  3. Hibernate: select user0_.USER_ID as USER_ID1_0_, user0_.USER_EMAIL as USER_EMA2_0_,
  4. user0_.USER_NAME as USER_NAM3_0_ from TBL_USERS user0_

我希望您能找到这个 Spring Hibernate Web 应用程序示例,以开始开发自己的应用程序。 这主要是针对初学者的,但是它将帮助您构建带有注解的任何带有 Hibernate 集成示例的 Spring MVC

学习愉快!

下载源码