精通 Spring Boot 系列 07
閱讀全文,約 23?分鐘
這是江帥帥的第009篇原創(chuàng)
Spring Boot 整合持久層開發(fā)
1、ORM
ORM(Object/Relation Mapping,對象/關(guān)系型數(shù)據(jù)庫映射)是一種規(guī)范,用于描述面向?qū)ο笳Z言到關(guān)系型數(shù)據(jù)庫的映射。
我們主要實現(xiàn)持久化類和數(shù)據(jù)表之間的映射,達到通過持久化類實現(xiàn)對數(shù)據(jù)表的操作。
ORM 有如下幾個基本的映射關(guān)系
數(shù)據(jù)表映射類
數(shù)據(jù)表的行映射對象(實例)
數(shù)據(jù)表的列(字段)映射對象的屬性
常見的 ORM 框架
Hibernate 是一個開源的框架
JPA(Java Persistence API,Java 持久化規(guī)范)
2、Spring Data JPA
亮點:極大地簡化了 JPA 的使用,在幾乎不用寫接口實現(xiàn)的情況下,就能完成對數(shù)據(jù)的訪問和操作。
Spring Data JPA 是 Spring Data 下的一個小模塊,Spring Data 提供了訪問操作數(shù)據(jù)的統(tǒng)一規(guī)范。
Spring Data 通過提供 Respository 接口來約定數(shù)據(jù)訪問的統(tǒng)一標準。
Respository 接口中常用的幾個子接口:
CrudRepository
PagingAndSortingRepository
JpaRepository
我們只需要定義數(shù)據(jù)訪問接口,然后實現(xiàn) Spring Data 提供的這些接口,然后就能實現(xiàn)對數(shù)據(jù)的操作了。
2.1 CrudRepository
使用 CrudRepository 接口訪問數(shù)據(jù)。
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 文件
添加數(shù)據(jù)源與 JPA 等基本配置信息。
####################
###?數(shù)據(jù)源信息配置?###
####################
#?數(shù)據(jù)庫地址
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
#?用戶名
spring.datasource.username=root
#?密碼
spring.datasource.password=1234
#?數(shù)據(jù)庫驅(qū)動
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#?指定連接池中最大的活躍連接數(shù).
spring.datasource.max-active=20
#?指定連接池最大的空閑連接數(shù)量.
spring.datasource.max-idle=8
#?指定必須保持連接的最小值
spring.datasource.min-idle=8
#?指定啟動連接池時,初始建立的連接數(shù)量
spring.datasource.initial-size=10
####################
###?JPA持久化配置?###
####################
#?指定數(shù)據(jù)庫的類型
spring.jpa.database=MySQL
#?指定是否需要在日志中顯示sql語句
spring.jpa.show-sql=true
#?指定自動創(chuàng)建|更新|驗證數(shù)據(jù)庫表結(jié)構(gòu)等配置,配置成update
#?表示如果數(shù)據(jù)庫中存在持久化類對應的表就不創(chuàng)建,不存在就創(chuàng)建對應的表
spring.jpa.hibernate.ddl-auto=update
#?Naming?strategy
#?指定命名策略
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
#?指定數(shù)據(jù)庫方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
3)創(chuàng)建 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?項目加載后會自動根據(jù)持久化類創(chuàng)建數(shù)據(jù)表
@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)創(chuàng)建 UserRepository 數(shù)據(jù)訪問接口
在這里,我們不需要提供實現(xiàn),只要直接繼承數(shù)據(jù)訪問接口就好。
package?nx.repository;
import?nx.bean.User;
import?org.springframework.data.repository.CrudRepository;
public?interface?UserRepository?extends?CrudRepository<User,?Integer>{
}
5)創(chuàng)建 UserService 業(yè)務層類
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);
????}
????/**
?????*?根據(jù)id刪除對象
?????*/
????@Transactional
????public?void?delete(int?id)?{
????????userRepository.deleteById(id);
????}
????/**
?????*?查詢所有數(shù)據(jù)
?????*/
????public?Iterable?getAll()? {
????????return?userRepository.findAll();
????}
????/**
?????*?根據(jù)id查詢數(shù)據(jù)
?????*/
????public?User?getById(Integer?id)?{
????????//?根據(jù)id查詢出對應的持久化對象
????????Optional?op?=?userRepository.findById(id);
????????return?op.get();
????}
????/**
?????*?修改用戶對象數(shù)據(jù),持久化對象修改會自動更新到數(shù)據(jù)庫
?????*/
????@Transactional
????public?void?update(User?user)?{
????????//?直接調(diào)用持久化對象的set方法修改對象的數(shù)據(jù)
????????user.setUsername("帥帥");
????????user.setLoginName("shuaishuai");
????}
}
6)創(chuàng)建控制器類
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?"保存數(shù)據(jù)成功!";
????}
????@RequestMapping("/update")
????public?String?update()?{
????????//?修改的對象必須是持久化對象,所以先從數(shù)據(jù)庫查詢出id為1的對象進行修改
????????User?user?=?userService.getById(1);
????????userService.update(user);
????????return?"修改數(shù)據(jù)成功!";
????}
????@RequestMapping("/delete")
????public?String?delete()?{
????????userService.delete(1);
????????return?"刪除數(shù)據(jù)成功!";
????}
????@RequestMapping("/getAll")
????public?Iterable?getAll()? {
????????return?userService.getAll();
????}
}
7)創(chuàng)建數(shù)據(jù)庫
CREATE?DATABASE?springbootdata;
8)訪問測試
瀏覽器,輸入 http://localhost:8080/user/getAll
2.2 PagingAndSortingRepository
PagingAndSortingRepository 繼承了 CrudRepository 接口,它還能實現(xiàn)分頁和排序的功能。
1)編輯 pom.xml 文件
與 CrudRepository 接口案例一樣
2)編輯 application.properties 文件
與 CrudRepository 接口案例一樣
3)創(chuàng)建 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 數(shù)據(jù)訪問接口
package?nx.repository;
import?nx.bean.Article;
import?org.springframework.data.repository.PagingAndSortingRepository;
public?interface?ArticleRepository?extends?PagingAndSortingRepository<Article,?Integer>?{
}
5)定義 ArticleService 業(yè)務層類
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?{
????//?注入數(shù)據(jù)訪問層接口對象?
????@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()? {
????????//?指定排序參數(shù)對象:根據(jù)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)? {
????????//?指定排序參數(shù)對象:根據(jù)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("查詢總頁數(shù):"?+?articleDatas.getTotalPages());
????????System.out.println("查詢總記錄數(shù):"?+?articleDatas.getTotalElements());
????????System.out.println("查詢當前第幾頁:"?+?articleDatas.getNumber()?+?1);
????????System.out.println("查詢當前頁面的記錄數(shù):"?+?articleDatas.getNumberOfElements());
????????//?查詢出的結(jié)果數(shù)據(jù)集合
????????List?articles?=?articleDatas.getContent();
????????System.out.println("查詢當前頁面的集合:"?+?articles);
????????return?articles;
????}
}
7)訪問測試
往數(shù)據(jù)表中添加一些數(shù)據(jù),然后就可以看到具體效果了。(此處略)

來源公眾號:江帥帥(ID:NXJSS666)
更多精彩?
獲取更多學習資料
視頻 |?面試 |?技術(shù) | 電子書?

