SpringBoot集成JPA实现分页和CRUD
文章目录
- SpringBoot集成JPA实现分页和CRUD
- pom.xml
- application.properties
- addCategory.jsp
- editCategory.jsp
- hello.jsp
- listCategory.jsp
- Category
- CategoryDAO
- CategoryService
- CategoryServiceImpl
- Page4Navigator
- RedisConfig
- CategoryController
- HelloController
懒得敲代码,直接拷贝: SpringBoot集成JPA实现分页和CRUD
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.moon</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot</name>
<description>springboot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!--要使用jsp添加这个-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!--数据库-->
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
填自己的数据库和密码
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
###########################redis#########################
#Redis数据库索引(默认为0)
spring.redis.database=0
#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=10
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=0
spring.jpa.show-sql=true
addCategory.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<div style="margin: 0px auto; width: 500px">
<form action="updateCategory" method="post">
name:<input name="name" value="${category.name}"><br>
<button type="submit">提交</button>
</form>
</div>
editCategory.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<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>
hello.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<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>
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"%>
<div align="center"></div>
<div style="width: 500px;margin: 20px auto;text-align: center">
<table align="center" border="1" cellspacing="0">
<caption>员工<a href="addCategory">添加</a></caption>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>编辑</th>
<th>删除</th>
</tr>
</thead>
<tbody>
<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>
</tbody>
</table>
<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>
<div>
</div>
</div>
Category
package com.moon.springboot.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
/**
* @Author moon
* @Date 2023/9/26 21:05
* @Description
*/
@Entity
@Table(name = "category_")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Category {
@Id
//表明自增长方式
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
}
CategoryDAO
package com.moon.springboot.dao;
import com.moon.springboot.pojo.Category;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @Author moon
* @Date 2023/9/26 21:18
* @Description
* 泛型<Category, Integer> 表示这个是针对Category类的DAO,Integer表示主键是Integer类型。
* JpaRepository 这个父接口,就提供了CRUD, 分页等等一系列的查询了
*/
public interface CategoryDAO extends JpaRepository<Category, Integer> {
}
CategoryService
package com.moon.springboot.service;
import com.moon.springboot.pojo.Category;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.data.domain.Pageable;
public interface CategoryService {
public Page4Navigator<Category> list(Pageable pageable);
public void save(Category category);
public void delete(int id);
public Category get(int id);
}
CategoryServiceImpl
package com.moon.springboot.service.impl;
import com.moon.springboot.dao.CategoryDAO;
import com.moon.springboot.pojo.Category;
import com.moon.springboot.service.CategoryService;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
@CacheConfig(cacheNames="category")
public class CategoryServiceImpl implements CategoryService {
@Autowired
CategoryDAO categoryDAO;
@Override
@Cacheable(key="'category '+#p0.offset + '-' + #p0.pageSize ")
public Page4Navigator<Category> list(Pageable pageable) {
Page<Category> pageFromJPA= categoryDAO.findAll(pageable);
Page4Navigator<Category> page = new Page4Navigator<>(pageFromJPA,5);
return page;
}
@Override
@Cacheable(key="'category '+ #p0")
public Category get(int id) {
Category c =categoryDAO.getOne(id);
return c;
}
@Override
@CacheEvict(allEntries=true)
// @CachePut(key="'category '+ #p0")
public void save(Category category) {
// TODO Auto-generated method stub
categoryDAO.save(category);
}
@Override
@CacheEvict(allEntries=true)
// @CacheEvict(key="'category '+ #p0")
public void delete(int id) {
// TODO Auto-generated method stub
categoryDAO.deleteById(id);
}
}
Page4Navigator
package com.moon.springboot.util;
import java.util.List;
import org.springframework.data.domain.Page;
public class Page4Navigator<T> {
Page<T> page4jpa;
//导航分页的页码数
int navigatePages;
//要打印的总页数
int totalPages;
int number;
long totalElements;
int size;
int numberOfElements;
List<T> content;
boolean isHasContent;
boolean first;
boolean last;
boolean isHasNext;
boolean isHasPrevious;
int[] navigatepageNums;
public Page4Navigator() {
//这个空的分页是为了 Redis 从 json格式转换为 Page4Navigator 对象而专门提供的
}
public Page4Navigator(Page<T> page4jpa,int navigatePages) {
this.page4jpa = page4jpa;
this.navigatePages = navigatePages;
totalPages = page4jpa.getTotalPages();
number = page4jpa.getNumber() ;
totalElements = page4jpa.getTotalElements();
size = page4jpa.getSize();
numberOfElements = page4jpa.getNumberOfElements();
content = page4jpa.getContent();
isHasContent = page4jpa.hasContent();
first = page4jpa.isFirst();
last = page4jpa.isLast();
isHasNext = page4jpa.hasNext();
isHasPrevious = page4jpa.hasPrevious();
calcNavigatepageNums();
}
private void calcNavigatepageNums() {
int navigatepageNums[];
int totalPages = getTotalPages();
int num = getNumber();
//当总页数小于或等于导航页码数时
if (totalPages <= navigatePages) {
navigatepageNums = new int[totalPages];
for (int i = 0; i < totalPages; i++) {
navigatepageNums[i] = i + 1;
}
} else { //当总页数大于导航页码数时
navigatepageNums = new int[navigatePages];
int startNum = num - navigatePages / 2;
int endNum = num + navigatePages / 2;
if (startNum < 1) {
startNum = 1;
//(最前navigatePages页
for (int i = 0; i < navigatePages; i++) {
navigatepageNums[i] = startNum++;
}
} else if (endNum > totalPages) {
endNum = totalPages;
//最后navigatePages页
for (int i = navigatePages - 1; i >= 0; i--) {
navigatepageNums[i] = endNum--;
}
} else {
//所有中间页
for (int i = 0; i < navigatePages; i++) {
navigatepageNums[i] = startNum++;
}
}
}
this.navigatepageNums = navigatepageNums;
}
public int getNavigatePages() {
return navigatePages;
}
public void setNavigatePages(int navigatePages) {
this.navigatePages = navigatePages;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public long getTotalElements() {
return totalElements;
}
public void setTotalElements(long totalElements) {
this.totalElements = totalElements;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getNumberOfElements() {
return numberOfElements;
}
public void setNumberOfElements(int numberOfElements) {
this.numberOfElements = numberOfElements;
}
public List<T> getContent() {
return content;
}
public void setContent(List<T> content) {
this.content = content;
}
public boolean isHasContent() {
return isHasContent;
}
public void setHasContent(boolean isHasContent) {
this.isHasContent = isHasContent;
}
public boolean isFirst() {
return first;
}
public void setFirst(boolean first) {
this.first = first;
}
public boolean isLast() {
return last;
}
public void setLast(boolean last) {
this.last = last;
}
public boolean isHasNext() {
return isHasNext;
}
public void setHasNext(boolean isHasNext) {
this.isHasNext = isHasNext;
}
public boolean isHasPrevious() {
return isHasPrevious;
}
public void setHasPrevious(boolean isHasPrevious) {
this.isHasPrevious = isHasPrevious;
}
public int[] getNavigatepageNums() {
return navigatepageNums;
}
public void setNavigatepageNums(int[] navigatepageNums) {
this.navigatepageNums = navigatepageNums;
}
}
RedisConfig
package com.moon.springboot.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.*;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();//value值使用json序列化器
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L))//设置缓存延时时间为30分钟
.disableCachingNullValues()//如果是空值,不缓存
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//设置key值序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));//设置value值序列化为json
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
.cacheDefaults(redisCacheConfiguration).build();
}
}
CategoryController
package com.moon.springboot.web;
import com.moon.springboot.pojo.Category;
import com.moon.springboot.service.CategoryService;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.beans.factory.annotation.Autowired;
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;
@Controller
public class CategoryController {
@Autowired
CategoryService categoryService;
@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 = Sort.by(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(start, size, sort);
Page4Navigator<Category> page =categoryService.list(pageable);
m.addAttribute("page", page);
return "listCategory";
}
@RequestMapping("/addCategory")
public String addCategory(Category c) throws Exception {
categoryService.save(c);
return "redirect:listCategory";
}
@RequestMapping("/deleteCategory")
public String deleteCategory(Category c) throws Exception {
categoryService.delete(c.getId());
return "redirect:listCategory";
}
@RequestMapping("/updateCategory")
public String updateCategory(Category c) throws Exception {
categoryService.save(c);
return "redirect:listCategory";
}
@RequestMapping("/editCategory")
public String editCategory(int id,Model m) throws Exception {
Category c= categoryService.get(id);
m.addAttribute("c", c);
return "editCategory";
}
}
HelloController
package com.moon.springboot.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.DateFormat;
import java.util.Date;
/**
* @Author moon
* @Date 2023/9/25 21:17
* @Description
*/
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model) {
model.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));
return "hello";
}
@RequestMapping("/hello_1")
public String hello_1(Model model) {
model.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));
return "hello_1";
}
}