阅读全文,约 23 分钟
这是江帅帅的第009篇原创
Spring Boot 整合持久层开发
1、ORM
ORM(Object/Relation Mapping,对象/关系型数据库映射)是一种规范,用于描述面向对象语言到关系型数据库的映射。
我们主要实现持久化类和数据表之间的映射,达到通过持久化类实现对数据表的操作。
ORM 有如下几个基本的映射关系
- 数据表映射类
- 数据表的行映射对象(实例)
- 数据表的列(字段)映射对象的属性
常见的 ORM 框架
- Hibernate 是一个开源的框架
- JPA(Java Persistence API,Java 持久化规范)
2、Spring Data JPA
亮点:极大地简化了 JPA 的使用,在几乎不用写接口实现的情况下,就能完成对数据的访问和操作。
Spring Data JPA 是 Spring Data 下的一个小模块,Spring Data 提供了访问操作数据的统一规范。
Spring Data 通过提供 Respository 接口来约定数据访问的统一标准。
Respository 接口中常用的几个子接口:
- CrudRepository
- PagingAndSortingRepository
- JpaRepository
我们只需要定义数据访问接口,然后实现 Spring Data 提供的这些接口,然后就能实现对数据的操作了。
2.1 CrudRepository
使用 CrudRepository 接口访问数据。
1)编辑 pom.xml 文件
添加 mysql-connector-java 和 spring-boot-starter-data-jpa 依赖模块,具体如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.nx</groupId> <artifactId>springbootdata</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> </parent> <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> <!-- 添加spring-boot-starter-web模块依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 添加MySQL依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 添加spring-boot-starter-thymeleaf模块依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- 添加Spring Data JPA依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
2)编辑 application.properties 文件
添加数据源与 JPA 等基本配置信息。
#################### ### 数据源信息配置 ### #################### # 数据库地址 spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true # 用户名 spring.datasource.username=root # 密码 spring.datasource.password=1234 # 数据库驱动 spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver # 指定连接池中最大的活跃连接数. spring.datasource.max-active=20 # 指定连接池最大的空闲连接数量. spring.datasource.max-idle=8 # 指定必须保持连接的最小值 spring.datasource.min-idle=8 # 指定启动连接池时,初始建立的连接数量 spring.datasource.initial-size=10 #################### ### JPA持久化配置 ### #################### # 指定数据库的类型 spring.jpa.database=MySQL # 指定是否需要在日志中显示sql语句 spring.jpa.show-sql=true # 指定自动创建|更新|验证数据库表结构等配置,配置成update # 表示如果数据库中存在持久化类对应的表就不创建,不存在就创建对应的表 spring.jpa.hibernate.ddl-auto=update # Naming strategy # 指定命名策略 spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy # 指定数据库方言 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
3)创建 User 持久化类
package nx.bean; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity // 此注解,会在 Spring Boot 项目加载后会自动根据持久化类创建数据表 @Table(name="tb_user") public class User implements Serializable{ private static final long serialVersionUID = 1L; /** * 使用@Id指定主键。使用代码@GeneratedValue(strategy=GenerationType.AUTO) * 指定主键的生成策略,mysql默认的是自增长。 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String username; private String loginName; private char sex; private int age; // getXxx & setXxx 方法 }
4)创建 UserRepository 数据访问接口
在这里,我们不需要提供实现,只要直接继承数据访问接口就好。
package nx.repository; import nx.bean.User; import org.springframework.data.repository.CrudRepository; public interface UserRepository extends CrudRepository<User, Integer>{ }
5)创建 UserService 业务层类
package nx.service; import java.util.Optional; import javax.annotation.Resource; import javax.transaction.Transactional; import nx.bean.User; import nx.repository.UserRepository; import org.springframework.stereotype.Service; @Service public class UserService { // 注入UserRepository @Resource private UserRepository userRepository; /** * save\update\delete * 方法需要绑定事务,使用@Transactional进行事务的绑定 * * 保存对象 * @param User * @return 包含自动生成的 id 的 User */ @Transactional public User save(User User) { return userRepository.save(User); } /** * 根据id删除对象 */ @Transactional public void delete(int id) { userRepository.deleteById(id); } /** * 查询所有数据 */ public Iterable<User> getAll() { return userRepository.findAll(); } /** * 根据id查询数据 */ public User getById(Integer id) { // 根据id查询出对应的持久化对象 Optional<User> op = userRepository.findById(id); return op.get(); } /** * 修改用户对象数据,持久化对象修改会自动更新到数据库 */ @Transactional public void update(User user) { // 直接调用持久化对象的set方法修改对象的数据 user.setUsername("帅帅"); user.setLoginName("shuaishuai"); } }
6)创建控制器类
package nx.controller; import javax.annotation.Resource; import nx.bean.User; import nx.service.UserService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/user") public class UserController { // 注入UserService @Resource private UserService userService; @RequestMapping("/save") public String save() { User user = new User(); user.setLoginName("mason"); user.setUsername("帅帅"); user.setSex('男'); user.setAge(18); user = userService.save(user); return "保存数据成功!"; } @RequestMapping("/update") public String update() { // 修改的对象必须是持久化对象,所以先从数据库查询出id为1的对象进行修改 User user = userService.getById(1); userService.update(user); return "修改数据成功!"; } @RequestMapping("/delete") public String delete() { userService.delete(1); return "删除数据成功!"; } @RequestMapping("/getAll") public Iterable<User> getAll() { return userService.getAll(); } }
7)创建数据库
CREATE DATABASE springbootdata;
8)访问测试
浏览器,输入 http://localhost:8080/user/getAll
2.2 PagingAndSortingRepository
PagingAndSortingRepository 继承了 CrudRepository 接口,它还能实现分页和排序的功能。
1)编辑 pom.xml 文件
与 CrudRepository 接口案例一样
2)编辑 application.properties 文件
与 CrudRepository 接口案例一样
3)创建 Article 持久化类
package nx.bean; import java.io.Serializable; import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * 商品对象 */ @Entity @Table(name="tb_article") public class Article implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String title; private String supplier; private Double price; private String locality; private Date putawayDate; private int storage; private String image; private String description; private Date createDate; // getXxx & setXxx 方法 }
4)定义 ArticleRepository 数据访问接口
package nx.repository; import nx.bean.Article; import org.springframework.data.repository.PagingAndSortingRepository; public interface ArticleRepository extends PagingAndSortingRepository<Article, Integer> { }
5)定义 ArticleService 业务层类
package nx.service; import javax.annotation.Resource; import nx.bean.Article; import nx.repository.ArticleRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; @Service public class ArticleService { // 注入数据访问层接口对象 @Resource private ArticleRepository articleRepository; public Iterable<Article> findAllSort(Sort sort) { return articleRepository.findAll(sort); } public Page<Article> findAll(Pageable page) { return articleRepository.findAll(page); } }
6)定义 ArticleController 控制器类
package nx.controller; import java.util.List; import javax.annotation.Resource; import nx.bean.Article; import nx.service.ArticleService; 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.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/article") public class ArticleController { // 注入ArticleService @Resource private ArticleService articleService; @RequestMapping("/sort") public Iterable<Article> sortArticle() { // 指定排序参数对象:根据id,进行降序查询 Sort.Order sort = new Sort.Order(Sort.Direction.DESC, "id"); Iterable<Article> articleDatas = articleService.findAllSort(sort.withProperties("id")); return articleDatas; } @RequestMapping("/pager") public List<Article> sortPagerArticle(int pageIndex) { // 指定排序参数对象:根据id,进行降序查询 Sort.Order sort = new Sort.Order(Sort.Direction.DESC, "id"); Pageable page = PageRequest.of(pageIndex - 1, 2, Sort.by(sort)); Page<Article> articleDatas = articleService.findAll(page); System.out.println("查询总页数:" + articleDatas.getTotalPages()); System.out.println("查询总记录数:" + articleDatas.getTotalElements()); System.out.println("查询当前第几页:" + articleDatas.getNumber() + 1); System.out.println("查询当前页面的记录数:" + articleDatas.getNumberOfElements()); // 查询出的结果数据集合 List<Article> articles = articleDatas.getContent(); System.out.println("查询当前页面的集合:" + articles); return articles; } }
7)访问测试
往数据表中添加一些数据,然后就可以看到具体效果了。(此处略)