SpringBoot integrates JPA to implement paging and CRUD
Article directory
- SpringBoot integrates JPA to implement paging and CRUD
-
- pom.xml
- application.properties
- addCategory.jsp
- editCategory.jsp
- hello.jsp
- listCategory.jsp
- Category
- CategoryDAO
- CategoryService
- CategoryServiceImpl
- Page4Navigator
- RedisConfig
- CategoryController
- HelloController
Too lazy to type the code, just copy:
SpringBoot integrates JPA to implement paging and 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> <!--To add this using 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> <!--Database--> <!-- 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
Fill in your own database and password
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 database index (default is 0) spring.redis.database=0 #Redis server address spring.redis.host=127.0.0.1 #Redis server connection port spring.redis.port=6379 #Redis server connection password (default is empty) spring.redis.password= #Maximum number of connections in the connection pool (use negative values to indicate no limit) spring.redis.pool.max-active=10 #The maximum blocking waiting time of the connection pool (use a negative value to indicate no limit) spring.redis.pool.max-wait=-1 #Maximum idle connection in the connection pool spring.redis.pool.max-idle=8 #Minimum idle connection in the connection pool spring.redis.pool.min-idle=0 #Connection timeout (milliseconds) 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">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">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">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>Employees<a href="addCategory">Add</a></caption> <thead> <tr> <th>id</th> <th>name</th> <th>Edit</th> <th>Delete</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}">Edit</a></td> <td><a href="deleteCategory?id=${c.id}">Delete</a></td> </tr> </c:forEach> </tbody> </table> <div> <a href="?start=0">【Home】</a> <a href="?start=${page.number-1}">【Previous page】</a> <a href="?start=${page.number + 1}">[Next page]</a> <a href="?start=${page.totalPages-1}">[Last page]</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 //Indicate the self-increasing method @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") privateInteger 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 * Generic <Category, Integer> indicates that this is a DAO for the Category class, and Integer indicates that the primary key is of Integer type. * JpaRepository, the parent interface, provides a series of queries such as CRUD, paging, etc. */ 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
When executing the query method, you can pass in a PageRequest object to represent paging query.
The PageRequest object represents the conditions and constraints of the query, usually including the current page number and several pieces of data per page.
You can also specify Direction or Sort when performing paging queries.
The result of the query is a Page object, which contains all data-related information on the current page.
Common methods of Page object:
getTotalPages() How many pages are there in total?
getTotalElements() How many pieces of data are there in total?
getNumber() gets the current page number
getSize() specifies how many elements there are on each page
getNumberOfElements() How many elements are actually on the current page?
hasContent() Whether the current page has data
getContent() gets all the data in the current page (List)
getSort() gets the paging query sorting rules
isFirst() Whether the current page is the first page
isLast() Whether the current page is the last page
hasPrevious() whether there is a previous page
hasNext() whether there is a next page
package com.moon.springboot.util; import java.util.List; import org.springframework.data.domain.Page; public class Page4Navigator<T> {<!-- --> Page<T> page4jpa; //Number of pages for navigation paging int navigatePages; //Total number of pages to print 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() {<!-- --> //This empty paging is specially provided for Redis to convert from json format to Page4Navigator object. } 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(); //When the total number of pages is less than or equal to the number of navigation pages if (totalPages <= navigatePages) {<!-- --> navigatepageNums = new int[totalPages]; for (int i = 0; i < totalPages; i + + ) {<!-- --> navigatepageNums[i] = i + 1; } } else {<!-- --> //When the total number of pages is greater than the number of navigation pages navigatepageNums = new int[navigatePages]; int startNum = num - navigatePages / 2; int endNum = num + navigatePages / 2; if (startNum < 1) {<!-- --> startNum = 1; //(The first navigationPages page for (int i = 0; i < navigatePages; i + + ) {<!-- --> navigatepageNums[i] = startNum + + ; } } else if (endNum > totalPages) {<!-- --> endNum = totalPages; //Last navigatePages page for (int i = navigatePages - 1; i >= 0; i--) {<!-- --> navigatepageNums[i] = endNum--; } } else {<!-- --> //All intermediate pages 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 value uses json serializer } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) {<!-- --> RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig(); redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L))//Set the cache delay time to 30 minutes .disableCachingNullValues()//If it is a null value, do not cache it .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//Set key value serialization .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));//Set the value value to be serialized into 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"; } }