使用Spring MVC,Spring Data JPA和Hibernate编写一个简单的Web应用程序

哈Ha! 我向您介绍Nam Ha Minh 编写的指南“ Spring MVC + Spring Data JPA + Hibernate-CRUD示例”的翻译。

在本Spring Java教程中,您将通过开发一个简单的Web应用程序来管理客户端信息,从而学习如何设置Spring MVC应用程序与Spring Data JPA一起使用。

完成本教程后,您可以基于Spring MVC和Spring Data JPA技术创建一个Java Web应用程序,如下所示:

图片

本指南中使用的程序和技术是:Java 8,Apache Tomcat 9,MySQL Server 5.7,Eclipse IDE 4.7(Oxygen),Spring Framework 5.1,Hibernate 5.4,Spring Data JPA 2.1.5和Servlet 3.1。

让我们从创建数据库开始。

1.创建数据库


我们将使用MySQL。 在我们的示例中,我们将使用客户表中的数据,该表位于名为sales的架构中。 客户表具有4个字段: idnameemailaddress

图片

您可以运行以下MySQL脚本来创建架构和表:

CREATE DATABASE `sales`; CREATE TABLE `customer` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `email` varchar(45) NOT NULL, `address` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

2.在Eclipse中创建一个项目


在Eclipse中创建一个动态Web项目,然后将其转换为Maven项目:为此,右键单击该项目,选择Configure> Convert to Maven Project 。 在打开的“ 创建新的POM”对话框中,输入以下信息:

-组ID: net.codejava
-工件ID: CustomerManager

还要确保Java项目的JRE版本是8或更高版本。

然后,打开pom.xml (Maven文件)为该项目配置依赖项。 声明Spring和Hibernate Framework的版本属性:

 <properties> <spring.version>5.1.5.RELEASE</spring.version> <hibernate.version>5.4.1.Final</hibernate.version> </properties> 

指定Spring框架的依赖关系:

 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> 

创建Spring MVC Web应用程序:

 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> 

要使用Spring Data JPA:

 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>2.1.5.RELEASE</version> </dependency> 

我们将Hibernate用作JPA实现,因此添加以下依赖项:

 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> 

为了使应用程序能够与MySQL一起使用,我们需要MySQL JDBC驱动程序的依赖项:

 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.14</version> <scope>runtime</scope> </dependency> 

现在是Java Servlet,JSP和JSTL的依赖项:

 <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> 

在项目的根目录创建两个Java包:
net.codejava.config :用于配置类。
net.codejava.customer :用于应用程序类。

3.创建一个JPA配置文件


由于我们使用JPA,因此需要在persistence.xml文件而不是hibernate.cfg.xml定义用于连接数据库的属性。 在项目的源文件夹中创建一个名为META-INF的新目录,将persistence.xml文件放入其中:

图片

然后在此文件中输入以下代码:

 <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1"> <persistence-unit name="SalesDB"> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sales" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="(password)" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" /> </properties> </persistence-unit> </persistence> 

如您所见,我们指定了用于连接数据库的属性,例如URL,用户,密码和JDBC驱动程序类。 另请注意,我们在配置代码中将使用名称SalesDB

4.创建模型类


创建一个映射到数据库中的customer表的Customer类,如下所示:

 package net.codejava.customer; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; private String address; protected Customer() { } protected Customer(String name, String email, String address) { this.name = name; this.email = email; this.address = address; } //       .       IDE,  . } 

如您所见,我们使用@Entity批注将此类映射到客户表(类名与表名相同)。 所有类的字段名称都与表中的字段名称相同。 id字段具有注释@Id@GeneratedValue以指示此字段是主键,并且其值是自动生成的。

5. Spring MVC和Spring Data JPA的配置


接下来,我们编写Java代码来配置Spring MVC和Spring Data JPA。 我们将使用基于Java的配置,因为它比XML更简单。

配置Spring Dispatcher Servlet


要在我们的应用程序中使用Spring MVC,我们需要在启动应用程序时通过编写以下类来注册Spring Dispatcher Servlet:

 package net.codejava.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class WebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext(); appContext.register(WebMvcConfig.class); ServletRegistration.Dynamic dispatcher = servletContext.addServlet( "SpringDispatcher", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } } 

当应用程序加载时,该类的onStartup()方法将由Servlet自动调用。 Spring Dispatcher Servlet通过匹配URL“ /”处理所有请求,并在WebMvcConfig类中查找配置,如下所述。

配置Spring MVC


net.codejava.config包中创建包含以下代码的WebMvcConfig类:

 package net.codejava.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("net.codejava ") public class WebMvcConfig { @Bean(name = "viewResolver") public InternalResourceViewResolver getViewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } } 

此类带有@Configuration批注标记,告诉Spring这是一个配置文件。 @ComponentScan告诉Spring在net.codejava包中查找配置类。

在此类中,我们创建一个通过为这些视图指定前缀和后缀来识别视图的bean。 因此,在WebContent/WEB-INF内创建views WebContent/WEB-INF以存储JSP文件。

在这里您可以添加其他Spring MVC配置。

配置Spring Data JPA


要使用Spring Data JPA,我们需要创建两个bean组件: EntityManagerFactoryJpaTransactionManager 。 因此,我们将创建另一个配置类JpaConfig

 package net.codejava.config; import javax.persistence.EntityManagerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalEntityManagerFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableJpaRepositories(basePackages = {"net.codejava.customer"}) @EnableTransactionManagement public class JpaConfig { @Bean public LocalEntityManagerFactoryBean entityManagerFactory() { LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean(); factoryBean.setPersistenceUnitName("SalesDB"); return factoryBean; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(entityManagerFactory); return transactionManager; } } 

在这里,我们使用两个重要的注释:

  • @EnableJpaRepositories :告诉Spring Data JPA在指定的包(net.codejava)中查找存储库类,以便在运行时注入适当的代码。
  • @EnableTransactionManagement :告诉Spring Data JPA生成代码以在运行时管理事务。

在此类中,第一个方法创建一个EntityManagerFactory来控制我们的SalesDB的持久性单元(此名称在上面的persistence.xml指定)。

最后一个方法为EntityManagerFactory创建JpaTransactionManagerEntityManagerFactory ,该实例是由先前方法创建的。

这是使用Spring Data JPA所需的最低配置。

创建一个存储库接口


创建一个CustomerRepository接口,以扩展Spring Data JPA中定义的CrudRepository接口:

 package net.codejava.customer; import java.util.List; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface CustomerRepository extends CrudRepository<Customer, Long> {    } 

这几乎是我们访问数据所需的所有代码。 只是同意? 使用Spring Data JPA,我们不需要编写DAO(Java数据访问对象)代码。 只需声明一个扩展CrudRepository接口的接口即可,该接口定义了CRUD方法,例如save()findAll()findById()deleteById()等。 在运行时,Spring Data JPA将自动生成代码。

请注意,扩展CrudRepository时,我们必须指定模型类的类型和主键字段的类型: CrudRepository<Customer, Long>

7.创建服务类


接下来,创建CustomerService类:

 package net.codejava.customer; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @Transactional public class CustomerService { @Autowired CustomerRepository repo; public void save(Customer customer) { repo.save(customer); } public List<Customer> listAll() { return (List<Customer>) repo.findAll(); } public Customer get(Long id) { return repo.findById(id).get(); } public void delete(Long id) { repo.deleteById(id); } } 

注意@Transactional批注@Transactional了我们的课程。 这意味着Spring Data JPA将拦截此类的所有方法以进行事务管理。 而且CustomerRepository接口实例将嵌入在此类中:

 @Autowired CustomerRepository repo; 

这似乎很神奇,因为我们没有编写DAO代码,但是Spring Data JPA将在运行时自动创建一个实现。

如您所见,此类中的所有方法都用于CRUD操作。 它只是将整个调用委托给CustomerRepository对象。 该类对于您来说似乎是多余的,但是有必要将业务/服务级别与存储库/ DAO级别分开。

8.创建一个Spring MVC Controller


创建一个类CustomerContoroller来处理来自客户的所有请求:

 package net.codejava.customer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class CustomerController { @Autowired private CustomerService customerService; //     } 

这是典型的Spring MVC Controller类,使用@Controller注释。 您可以看到使用@Autowired批注将CustomerService实例注入到该对象中。

我们将在以下各节中编写处理方法。

9.添加客户列表


所有客户都将显示在我们应用程序的主页上,为此,请将适当的处理方法添加到我们的CustomerController类中:

 @RequestMapping("/") public ModelAndView home() { List<Customer> listCustomer = customerService.listAll(); ModelAndView mav = new ModelAndView("index"); mav.addObject("listCustomer", listCustomer); return mav; } 

浏览主页( index.jsp )应如下所示:

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Customer Manager</title> </head> <body> <div align="center"> <h2>Customer Manager</h2> <form method="get" action="search"> <input type="text" name="keyword" />  <input type="submit" value="Search" /> </form> <h3><a href="/new">New Customer</a></h3> <table border="1" cellpadding="5"> <tr> <th>ID</th> <th>Name</th> <th>E-mail</th> <th>Address</th> <th>Action</th> </tr> <c:forEach items="${listCustomer}" var="customer"> <tr> <td>${customer.id}</td> <td>${customer.name}</td> <td>${customer.email}</td> <td>${customer.address}</td> <td> <a href="/edit?id=${customer.id}">Edit</a>   <a href="/delete?id=${customer.id}">Delete</a> </td> </tr> </c:forEach> </table> </div> </body> </html> 

现在,您可以启动Web应用程序。 在客户表中添加几行,然后转到http://localhost:8080/CustomerManager/ ,您将看到类似的内容:

图片

10.添加一个新用户


为了实现创建新客户端的功能,我们需要编写两个处理程序方法。 第一个将显示用于添加客户端的新表单:

 @RequestMapping("/new") public String newCustomerForm(Map<String, Object> model) { Customer customer = new Customer(); model.put("customer", customer); return "new_customer"; } 

让我们用名称new_customer.jsp编写JSP表单本身:

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"    pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>     <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"    "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>New Customer</title> </head> <body>    <div align="center">        <h2>New Customer</h2>        <form:form action="save" method="post" modelAttribute="customer">            <table border="0" cellpadding="5">                <tr>                    <td>Name: </td>                    <td><form:input path="name" /></td>                </tr>                <tr>                    <td>Email: </td>                    <td><form:input path="email" /></td>                </tr>                <tr>                    <td>Address: </td>                    <td><form:input path="address" /></td>                </tr>                   <tr>                    <td colspan="2"><input type="submit" value="Save"></td>                </tr>                               </table>        </form:form>    </div> </body> </html> 

现在,在主页上,您将看到“ 新客户”链接,单击该链接时,您将看到一个新表单:

图片

第二个处理程序方法将以以下形式处理“ 保存”按钮:

 @RequestMapping(value = "/save", method = RequestMethod.POST) public String saveCustomer(@ModelAttribute("customer") Customer customer) { customerService.save(customer); return "redirect:/"; } 

如您所见,成功保存用户后,它将客户端重定向到主页。

11.更改用户数据


要实现客户端编辑功能,请将以下处理程序方法添加到CustomerController类:

 @RequestMapping("/edit") public ModelAndView editCustomerForm(@RequestParam long id) {    ModelAndView mav = new ModelAndView("edit_customer");    Customer customer = customerService.get(id);    mav.addObject("customer", customer);    return mav; } 

让我们编写edit_customer.jsp表单,此方法调用该表单:

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Edit Customer</title> </head> <body> <div align="center"> <h2>Edit Customer</h2> <form:form action="save" method="post" modelAttribute="customer"> <table border="0" cellpadding="5"> <tr> <td>ID: </td> <td>${customer.id} <form:hidden path="id"/> </td> </tr> <tr> <td>Name: </td> <td><form:input path="name" /></td> </tr> <tr> <td>Email: </td> <td><form:input path="email" /></td> </tr> <tr> <td>Address: </td> <td><form:input path="address" /></td> </tr> <tr> <td colspan="2"><input type="submit" value="Save"></td> </tr> </table> </form:form> </div> </body> </html> 

单击主页上客户端旁边的“ 编辑”超链接,将调用客户端编辑表单,该表单如下所示:



处理程序方法仍处理“ 保存”按钮。

12.删除客户端


要实现删除功能,请在CustomerController类中编写以下处理程序方法:

 @RequestMapping("/delete") public String deleteCustomerForm(@RequestParam long id) { customerService.delete(id); return "redirect:/"; } 

单击主页上客户端旁边的“ 删除”超链接。 客户端将被删除,列表将被更新。

13.按客户搜索


最后,让我们实现一个搜索功能,该功能允许用户通过输入关键字来搜索客户。 搜索功能在三个字段中搜索关键字:名称,电子邮件和地址,我们需要在CustomerRepository界面中为其编写自己的方法:

 package net.codejava.customer; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; public interface CustomerRepository extends CrudRepository<Customer, Long> { @Query(value = "SELECT c FROM Customer c WHERE c.name LIKE '%' || :keyword || '%'" + " OR c.email LIKE '%' || :keyword || '%'" + " OR c.address LIKE '%' || :keyword || '%'") public List<Customer> search(@Param("keyword") String keyword); } 

search()方法只是用@Query注释的抽象方法。 搜索查询是一个JPA查询。

然后将方法添加到CustomerService类:

 public List<Customer> search(String keyword) { return repo.search(keyword); } 

现在将处理程序方法添加到CustomerController类:

 @RequestMapping("/search") public ModelAndView search(@RequestParam String keyword) { List<Customer> result = customerService.search(keyword); ModelAndView mav = new ModelAndView("search"); mav.addObject("result", result); return mav; } 

并创建一个search.jsp搜索结果search.jsp

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Search Result</title> </head> <body> <div align="center"> <h2>Search Result</h2> <table border="1" cellpadding="5"> <tr> <th>ID</th> <th>Name</th> <th>E-mail</th> <th>Address</th> </tr> <c:forEach items="${result}" var="customer"> <tr> <td>${customer.id}</td> <td>${customer.name}</td> <td>${customer.email}</td> <td>${customer.address}</td> </tr> </c:forEach> </table> </div> </body> </html> 

要测试搜索功能,请在主页上的搜索字段中输入关键字,然后按Enter。 您将看到搜索结果页面:


结论


在本指南中,您学习了如何使用Spring Data JPA开发Spring MVC Web应用程序来访问数据。 如您所见,Spring Data JPA大大减少并简化了我们需要编写的代码。

为了进行比较,这是Eclipse IDE中的项目结构:


感谢您的阅读!

Source: https://habr.com/ru/post/zh-CN479286/


All Articles