精通 Spring Boot 系列文(7)
阅读全文,约 23 分钟
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 依赖模块,具体如下:
<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.0modelVersion>
<groupId>com.nxgroupId>
<artifactId>springbootdataartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.6.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
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 getAll() {
return userRepository.findAll();
}
/**
* 根据id查询数据
*/
public User getById(Integer id) {
// 根据id查询出对应的持久化对象
Optional 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 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 findAllSort(Sort sort) {
return articleRepository.findAll(sort);
}
public Page 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 sortArticle() {
// 指定排序参数对象:根据id,进行降序查询
Sort.Order sort = new Sort.Order(Sort.Direction.DESC, "id");
Iterable articleDatas = articleService.findAllSort(sort.withProperties("id"));
return articleDatas;
}
@RequestMapping("/pager")
public List 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 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 articles = articleDatas.getContent();
System.out.println("查询当前页面的集合:" + articles);
return articles;
}
}
7)访问测试
往数据表中添加一些数据,然后就可以看到具体效果了。(此处略)
Java后端编程
更多Java推文,关注公众号