前置:Jsp视图
Springboot的默认视图支持是Thymeleaf,还没学到,jsp用起来比较熟,先用它过渡一下。
1、在pom.xml中添加对Jsp的支持:
<!-- servlet依赖. --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- tomcat的支持.,用于编译jsp--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency>
application.properties配置:
spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp
这个是jsp文件的前置和后缀,在webapp下新建WEB-INF文件夹,在WEB-INF下新建jsp文件夹,jsp文件就放在这,关于jsp的配置就完成了,也可以写个Controller和jsp来测试一下是否配置成功。
一、整合JPA
我以前是没见过这玩意的,先了解一下JPA:
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA 的目标之一是制定一个可以由很多供应商实现的API,并且开发人员可以编码来实现该API,而不是使用私有供应商特有的API。
JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个,应该说无人能出其右。从功能上来说,JPA就是Hibernate功能的一个子集。
1、在pom.xml中添加相应的依赖添加依赖:
添加spring-boot-starter-jdbc依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa </artifactId> </dependency>
添加mysql连接类和连接池类:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
完整的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>edu.hpu</groupId> <artifactId>SpringBoot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SpringBoot</name> <!-- Spring Boot 启动父依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <dependencies> <!-- Spring Boot web依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 添加servlet依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!--添加 jstl依赖 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!-- 用于编译jsp --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- 热部署依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> <!-- 这个需要为 true 热部署才有效 --> </dependency> <!-- 添加对mysql的支持 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.21</version> </dependency> <!-- 添加对jpa的支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2、数据源
JPA是干什么的,是搞数据库持久化的,我们得有数据。这里数据库用的是mysql.
创建数据库:
create database springbootjpa;
创建表:
use springbootjpa; CREATE TABLE category_ ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(30), PRIMARY KEY (id) ) DEFAULT CHARSET=UTF8;
添加数据:
这个看着随便添加吧。
3、数据源配置:
在application中配置相应数据源,
spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=xing0515 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=update
完整的application.properties:
spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=xing0515 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=update
4、创建实体类
新建一个包edu.hpu.springboot.pojo,在包下新建实体类Category,代码如下:
package edu.hpu.springboot.pojo; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; //对应category_的实体类 @Entity //表示这是个实体类 @Table(name="category_") //表示对应的表 public class Category { @Id //表示主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //表明自增长方式 @Column(name="id") //表示对应的字段 private int id; @Column private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Category [id=" + id + ", name=" + name + "]"; } }
关于相应注解:
注解 | 解释 |
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(一个表中的主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置 |
@AccessType(FIELD ) | 则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQueries | 指定命名查询的列表。 |
@NamedQuery | 指定使用静态名称的查询 |
5、CategoryDao
新建包edu.hpu.springoot.dao,在包下新建接口CategoryDao,继承继承了JpaRepository,并且提供泛型<Category,Integer> 表示这个是针对Category类的DAO,Integer表示主键是Integer类型。
package edu.hpu.springboot.dao; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import edu.hpu.springboot.pojo.*; /*继承了JpaRepository,并且提供泛型<Category,Integer> * 表示这个是针对Category类的DAO,Integer表示主键是Integer类型 * JpaRepository 这个父接口,就提供了CRUD, 分页等等一系列的查询了,直接拿来用 */ public interface CategoryDao extends JpaRepository<Category, Integer>{ public List<Category> findByName(String name); public List<Category> findByNameLikeAndIdGreaterThanOrderByNameAsc(String name, int id); }
JpaRepository提供的一些预先生成方法:
还可以自定义一些查询,后面再看。
6、CategoryController
这个省略了Service,一般是不能省略的,新建包edu…hpu.springboot.web,创建类CategoryController
package edu.hpu.springboot.web; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.how2java.springboot.dao.CategoryDAO; import com.how2java.springboot.pojo.Category; @Controller public class CategoryController { @Autowired CategoryDAO categoryDAO; @RequestMapping("/listCategory") public String listCategory(Model m) throws Exception { List<Category> cs=categoryDAO.findAll(); m.addAttribute("cs", cs); return "listCategory"; } }
7、listCategory.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <table align='center' border='1' cellspacing='0'> <tr> <td>id</td> <td>name</td> </tr> <c:forEach items="${cs}" var="c" varStatus="st"> <tr> <td>${c.id}</td> <td>${c.name}</td> </tr> </c:forEach> </table>
8、启动Application,访问网址http://127.0.0.1:8080/listCategory
官方文档也看了一下,不是想象中的那么费劲,有空可以仔细看看,提升一下自己的英文文档阅读能力。Accessing Data with JPA
二、CRUD+分页
1、修改CategoryController,增加、删除、获取、修改映射
package edu.hpu.springboot.web; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import edu.hpu.springboot.dao.CategoryDao; import edu.hpu.springboot.pojo.Category; @Controller public class CategoryController { @Autowired CategoryDao categoryDao; @RequestMapping("/addCategory") public String addCategory(Category c) throws Exception{ categoryDao.save(c); return "redirect:listCategory"; } @RequestMapping("/deleteCategory") public String deleteCategory(Category c) throws Exception{ categoryDao.delete(c); return "redirect:listCategory"; } @RequestMapping("/editCategory") public String editCategory(int id,Model m) throws Exception{ Category c=categoryDao.findOne(id); m.addAttribute("c", c); return "editCategory"; } @RequestMapping("/updateCategory") public String updateCategory(Category c) throws Exception{ categoryDao.save(c); return "redirect:listCategory"; } @RequestMapping("/listCategory") public String listCategory(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value="size",defaultValue="5")int size) throws Exception{ start = start<0?0:start; Sort sort=new Sort(Sort.Direction.DESC, "id"); Pageable pageable=new PageRequest(start, size, sort); Page<Category> page=categoryDao.findAll(pageable); System.out.println(page.getNumber()); System.out.println(page.getNumberOfElements()); System.out.println(page.getSize()); System.out.println(page.getTotalElements()); System.out.println(page.getTotalPages()); m.addAttribute("page", page); return "listCategory"; } }
查询映射也做了相应的更改:
(1)、 在参数里接受当前是第几页 start ,以及每页显示多少条数据 size。 默认值分别是0和5。
(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value = "size", defaultValue = "5") int size)
(2)、 如果 start 为负,那么修改为0. 这个事情会发生在当前是首页,并点击了上一页的时候
start = start<0?0:start;
(3)、 设置倒排序
Sort sort = new Sort(Sort.Direction.DESC, "id");
(4)、 根据start,size和sort创建分页对象
Pageable pageable = new PageRequest(start, size, sort);
(5)、 CategoryDAO根据这个分页对象获取结果page.
Page<Category> page =categoryDAO.findAll(pageable);
在这个page对象里,不仅包含了分页信息,还包含了数据信息,即有哪些分类数据。 这个可以通过getContent()获取出来。
(6)、把page放在"page"属性里,跳转到listCategory.jsp
m.addAttribute("page", page); return "listCategory";
2、listCategory.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ 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=UTF-8"> <title>查看分类</title> </head> <body> <div style="width: 500px; margin: 20px auto; text-align: center"> <table align='center' border='1' cellspacing='0'> <tr> <td>id</td> <td>name</td> <td>编辑</td> <td>删除</td> </tr> <c:forEach items="${page.content}" var="c" varStatus="st"> <tr> <td>${c.id}</td> <td>${c.name}</td> <td><a href="editCategory?id=${c.id}">编辑</a></td> <td><a href="deleteCategory?id=${c.id}">删除</a></td> </tr> </c:forEach> </table> <br> <div> <a href="?start=0">[首 页]</a> <a href="?start=${page.number-1}">[上一页]</a> <a href="?start=${page.number+1}">[下一页]</a> <a href="?start=${page.totalPages-1}">[末 页]</a> </div> <br> <form action="addCategory" method="post"> name: <input name="name"> <br> <button type="submit">提交</button> </form> </body> </html>
3、editCategory.jsp
修改分类:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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=UTF-8"> <title>修改</title> </head> <body> <div style="margin: 0px auto; width: 500px"> <form action="updateCategory" method="post"> name: <input name="name" value="${c.name}"> <br> <input name="id" type="hidden" value="${c.id}"> <button type="submit">提交</button> </form> </div> </body> </html>
4、运行
由于采用的是热部署,直接访问
5、最后再加一点JPA的拓展:自定义简单查询
自定义的简单查询就是根据方法名来自动生成 SQL,主要的语法是findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy后面跟属性名称:
Category findByCategoryName(String name);
也使用一些加一些关键字And 、 Or
Category findByCategoryNameOrId(String name,int id);
JPA同样可以实现复杂查询——分页查询、限制查询,
自定义SQL查询
多表查询
直接参考,用时再查:
Spring Boot(五):Spring Boot Jpa 的使用
Spring Data JPA - Reference Documentation