精通 Spring Boot 系列 07

JAVA公众号

共 9404字,需浏览 19分钟

 ·

2020-08-28 18:54

阅读全文,约 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 依赖模块,具体如下:


<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<UserInteger>{
}

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<ArticleInteger{
}

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 - 12, 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)访问测试

往数据表中添加一些数据,然后就可以看到具体效果了。(此处略)


来源公众号:江帅帅(ID:NXJSS666)

更多精彩?


在公众号【程序员编程】对话框输入以下关键词
查看更多优质内容!

大数据 | Java | 1024 | 电子书 | 速查表 
Python进阶 | 面试 | 手册 | 成神 | 思想 | 小程序
命令行 | 人工智能 | 软件测试 | Web前端 | Python

扫码关注我们

获取更多学习资料

视频 | 面试 | 技术 | 电子书 

浏览 40
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报