笔记65 Spring Boot快速入门(五)

SpringBoot+JPA

一、什么是JPA?

  JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。真正干活的可能是Hibernate,TopLink等等实现了JPA规范的不同厂商,默认是Hibernate。

二、在springboot中使用JPA对数据库进行抽插

(一)目录结构

(二)pom.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5 
 6     <groupId>com.example</groupId>
 7     <artifactId>springboot-jpa-demo</artifactId>
 8     <version>0.0.1-SNAPSHOT</version>
 9     <packaging>jar</packaging>
10 
11     <name>springboot-jpa-demo</name>
12     <description>Demo project for Spring Boot</description>
13 
14     <parent>
15         <groupId>org.springframework.boot</groupId>
16         <artifactId>spring-boot-starter-parent</artifactId>
17         <version>1.5.9.RELEASE</version>
18         <relativePath/> <!-- lookup parent from repository -->
19     </parent>
20 
21     <properties>
22         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24         <java.version>1.8</java.version>
25     </properties>
26 
27     <dependencies>
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-data-jpa</artifactId>
31         </dependency>
32         <dependency>
33             <groupId>org.springframework.boot</groupId>
34             <artifactId>spring-boot-starter-jdbc</artifactId>
35         </dependency>
36         <dependency>
37             <groupId>org.springframework.boot</groupId>
38             <artifactId>spring-boot-starter-tomcat</artifactId>
39         </dependency>
40         <dependency>
41             <groupId>org.springframework.boot</groupId>
42             <artifactId>spring-boot-starter-web</artifactId>
43         </dependency>
44 
45         <dependency>
46             <groupId>mysql</groupId>
47             <artifactId>mysql-connector-java</artifactId>
48             <version>5.1.21</version>
49         </dependency>
50         <dependency>
51             <groupId>org.springframework.boot</groupId>
52             <artifactId>spring-boot-starter-test</artifactId>
53             <scope>test</scope>
54         </dependency>
55 
56         <dependency>
57             <groupId>org.springframework.boot</groupId>
58             <artifactId>spring-boot-starter-thymeleaf</artifactId>
59         </dependency>
60     </dependencies>
61 
62     <build>
63         <plugins>
64             <plugin>
65                 <groupId>org.springframework.boot</groupId>
66                 <artifactId>spring-boot-maven-plugin</artifactId>
67             </plugin>
68         </plugins>
69     </build>
70 
71 
72 </project>

1.数据库准备:创建表,插入数据等(略)

给出application.properties

1 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sh?characterEncoding=UTF-8
2 spring.datasource.username=root
3 spring.datasource.password=123456
4 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
5 spring.jpa.properties.hibernate.hbm2ddl.auto=update
6 
7 server.port=8080
8 server.context-path=/Test·

2.IDEA新建项目(列出比较重要的步骤)

3.新建pojo——Category

 1 package com.example.springbootjpademo.pojo;
 2 
 3 import javax.persistence.*;
 4 
 5 @Entity
 6 @Table(name = "category")
 7 public class Category {
 8     @Id
 9     @GeneratedValue(strategy = GenerationType.IDENTITY)
10     @Column(name = "id")
11     private int id;
12 
13     @Column(name = "name")
14     private String name;
15     public int getId() {
16         return id;
17     }
18     public void setId(int id) {
19         this.id = id;
20     }
21     public String getName() {
22         return name;
23     }
24     public void setName(String name) {
25         this.name = name;
26     }
27 }

4.创建DAO

  创建dao接口CategoryDAO,继承了JpaRepository,并且提供泛型<Category,Integer> 表示这个是针对Category类的DAO,Integer表示主键是Integer类型。
  JpaRepository 这个父接口,就提供了CRUD, 分页等等一系列的查询了,直接拿来用,都不需要二次开发的了。

1 package com.example.springbootjpademo.dao;
2 
3 import com.example.springbootjpademo.pojo.Category;
4 import org.springframework.data.jpa.repository.JpaRepository;
5 
6 public interface CategoryDAO extends JpaRepository<Category,Integer> {
7 }

5.创建Controller

自动加载CategoryDAO,然后调用findAll()查询所有条目。

 1 package com.example.springbootjpademo.controller;
 2 
 3 import com.example.springbootjpademo.dao.CategoryDAO;
 4 import com.example.springbootjpademo.pojo.Category;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Controller;
 7 import org.springframework.ui.Model;
 8 import org.springframework.web.bind.annotation.RequestMapping;
 9 
10 import java.util.List;
11 @Controller
12 public class CategoryController {
13     @Autowired
14     CategoryDAO categoryDAO;
15 
16     @RequestMapping("/listCategory")
17     public  String ListCategory(Model model) throws Exception{
18         List<Category> categoryList=categoryDAO.findAll();
19         model.addAttribute("categories",categoryList);
20         return "listCategory";
21     }
22 }

6.创建view(使用Thymeleaf)

listCategory.html

 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <div class="showing">
 9     <h2>springboot+jpa</h2>
10 
11     <table>
12         <thead>
13         <tr>
14             <th>id</th>
15             <th>name</th>
16         </tr>
17         </thead>
18         <tbody>
19         <tr th:each="c: ${categories}">
20             <td align="center" th:text="${c.id}"></td>
21             <td align="center" th:text="${c.name}"></td>
22         </tr>
23         </tbody>
24     </table>
25 </div>
26 </body>
27 </html>

7.测试

三、总结(目前遇到的问题,可能有出入)

1.注意springboot自动扫描和装配的规则。

SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描!

“Application类”是指SpringBoot项目入口类。这个类的位置很关键:
如果Application类所在的包为:com.boot.app,则只会扫描com.boot.app包及其所有子包,如果service或dao所在包不在com.boot.app及其子包下,则不会被扫描!
即, 把Application类放到dao、service所在包的上级,com.boot.Application

2.jpa与2.0.3版本的springboot之间存在冲突,会导致项目出现问题。

3.JpaRepository 继承PagingAndSortingRepository,实现一组JPA规范相关的方法。

<1>什么是Repository

  Repository(资源库):通过用来访问领域对象的一个类似集合的接口,在领域与数据映射层之间进行协调。这个叫法就类似于我们通常所说的DAO,在这里,我们就按照这一习惯把数据访问层叫Repository 
  Spring Data给我们提供几个Repository,基础的Repository提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下: 

Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别 
CrudRepository: 继承Repository,实现了一组CRUD相关的方法 

PagingAndSortingRepository: 继承CrudRepository,实现了一组分页排序相关的方法 

JpaRepository: 继承PagingAndSortingRepository,实现一组JPA规范相关的方法 

JpaSpecificationExecutor: 比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法 
我们自己定义的XxxxRepository需要继承JpaRepository,这样我们的XxxxRepository接口就具备了通用的数据访问控制层的能力。

<2>CrudRepository接口

T save(T entity);//保存单个实体 
Iterable<T> save(Iterable<? extends T> entities);//保存集合 
T findOne(ID id);//根据id查找实体 
boolean exists(ID id);//根据id判断实体是否存在 
Iterable<T> findAll();//查询所有实体,不用或慎用! 
long count();//查询实体数量 
void delete(ID id);//根据Id删除实体 
void delete(T entity);//删除一个实体 
void delete(Iterable<? extends T> entities);//删除一个实体的集合 
void deleteAll();//删除所有实体,不用或慎用! 

<3>PagingAndSortingRepository接口

  这个接口提供了分页与排序功能 
  Iterable<T> findAll(Sort sort);//排序 
    Page<T> findAll(Pageable pageable);//分页查询(含排序功能) 

<4>JpaRepository接口

  这个接口提供了JPA的相关功能 
  List<T> findAll();//查找所有实体 
    List<T> findAll(Sort sort);//排序 查找所有实体 
    List<T> save(Iterable<? extends T> entities);//保存集合 
    void flush();//执行缓存与数据库同步 
    T saveAndFlush(T entity);//强制执行持久化 
  void deleteInBatch(Iterable<T> entities);//删除一个实体集合 
 

四、使用JPA进行CRUD和分页

1.在CategoryController中添加映射:增、删、改、查。

 1     @RequestMapping("/listCategories")
 2     public  String ListCategories(Model model,
 3                                   @RequestParam(value = "start",defaultValue = "0")int start,
 4                                   @RequestParam(value = "size",defaultValue = "5") int size
 5                                   ) throws Exception{
 6         start=start<0?0:start;
 7         Sort sort=new Sort(Sort.Direction.DESC,"id");
 8         Pageable pageable=new PageRequest(start,size,sort);
 9         Page<Category> page=categoryDAO.findAll(pageable);
10         model.addAttribute("page",page);
11         return "listCategories";
12     }
13 
14     //JPA 新增和修改用的都是save. 它根据实体类的id是否为0来判断是进行增加还是修改
15     @RequestMapping("/addCategory")
16     public String addCategory(Category category) throws Exception{
17         categoryDAO.save(category);
18         return "redirect:listCategories";
19     }
20     @RequestMapping("/deleteCategory")
21     public String deleteCategory(Category category)throws Exception{
22         categoryDAO.delete(category);
23         return "redirect:listCategories";
24     }
25     @RequestMapping("/updateCategory")
26     public String updateCategory(Category category)throws Exception{
27         categoryDAO.save(category);
28         return "redirect:listCategories";
29     }
30     @RequestMapping("/editCategory")
31     public String editCategory(int id,Model model)throws Exception{
32         Category category=categoryDAO.getOne(id);
33         model.addAttribute("category",category);
34         return "editCategory";
35     }

知识点:

<1>Page是Spring Data提供的一个接口,该接口表示一部分数据的集合以及其相关的下一部分数据、数据总数等相关信息,通过该接口,我们可以得到数据的总体信息(数据总数、总页数...)以及当前数据的信息(当前数据的集合、当前页数等)。

 1 public interface Page<T> extends Iterable<T> {
 2  
 3     int getNumber();            //当前第几页   返回当前页的数目。总是非负的
 4  
 5     int getSize();                //返回当前页面的大小。
 6  
 7     int getTotalPages();         //返回分页总数。
 8  
 9     int getNumberOfElements();   //返回当前页上的元素数。
10  
11     long getTotalElements();    //返回元素总数。
12  
13     boolean hasPreviousPage();  //返回如果有上一页。
14  
15     boolean isFirstPage();      //返回当前页是否为第一页。
16  
17     boolean hasNextPage();      //返回如果有下一页。
18  
19     boolean isLastPage();       //返回当前页是否为最后一页。
20  
21     Iterator<T> iterator();
22  
23     List<T> getContent();     //将所有数据返回为List
24  
25     boolean hasContent();     //返回数据是否有内容。
26  
27     Sort getSort();          //返回页的排序参数。
28 }

<2>Pageable 是Spring Data库中定义的一个接口,该接口是所有分页相关信息的一个抽象,通过该接口,我们可以得到和分页相关所有信息(例如pageNumber、pageSize等),这样,Jpa就能够通过pageable参数来得到一个带分页信息的Sql语句。

 1 /**
 2  * 分页信息抽象接口
 3  * 
 4  * @author Oliver Gierke
 5  */
 6 public interface Pageable {
 7  
 8     /**
 9      * 返回要返回的页面.
10      * 
11      * @return the page to be returned.
12      */
13     int getPageNumber();
14  
15     /**
16      * 返回要返回的项目的数量。
17      * 
18      * @return the number of items of that page
19      */
20     int getPageSize();
21  
22     /**
23      * 根据底层页面和页面大小返回偏移量。
24      * 
25      * @return the offset to be taken
26      */
27     int getOffset();
28  
29     /**
30      * 返回排序参数。
31      * 
32      * @return
33      */
34     Sort getSort();
35 }

2.数据展示页listCategories.html

 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <div class="showing">
 9     <h2>springboot+jpa</h2>
10     <div style="500px;margin:20px auto;text-align: center">
11         <table align="center" border="1" cellspacing="0">
12             <thead>
13             <tr>
14                 <th>id</th>
15                 <th>name</th>
16                 <td>编辑</td>
17                 <td>删除</td>
18             </tr>
19             </thead>
20             <tbody>
21             <tr th:each="c: ${page}">
22                 <td align="center" th:text="${c.id}"></td>
23                 <td align="center" th:text="${c.name}"></td>
24                 <td align="center" ><a th:href="@{/editCategory(id=${c.id})}">编辑</a></td>
25                 <td align="center" ><a th:href="@{/deleteCategory(id=${c.id})}">删除</a></td>
26             </tr>
27             </tbody>
28         </table>
29         <br />
30         <div>
31             <a th:href="@{/listCategories(start=0)}">[首  页]</a>
32             <a th:href="@{/listCategories(start=${page.number -1})}">[上一页]</a>
33             <a th:href="@{/listCategories(start=${page.number +1})}">[下一页]</a>
34             <a th:href="@{/listCategories(start=${page.totalPages -1})}">[末  页]</a>
35         </div>
36         <form action="/addCategory" method="post">
37             name:<input name="name"/><br/>
38             <button type="submit">提交</button>
39         </form>
40     </div>
41 </div>
42 </body>
43 </html>

3.修改页面editCategory.html

 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <div class="showing">
 9     <h2>springboot+jpa</h2>
10 
11     <div style="margin:0px auto; 500px">
12 
13         <form action="/updateCategory" method="post">
14 
15             name: <input name="name" th:value="${category.name}" /> <br/>
16 
17             <input name="id" type="hidden" th:value="${category.id}" />
18             <button type="submit">提交</button>
19 
20         </form>
21     </div>
22 </div>
23 </body>
24 </html>

4.测试

 五、代码

https://github.com/lyj8330328/springboot-jpa-demo

原文地址:https://www.cnblogs.com/lyj-gyq/p/9301532.html