Spring Boot入坑-5-数据访问

概述

  • 程序中的各种数据,包括业务、日志、监控、行为等数据都需要存储起来,存储数据的就是数据库,常指关系型数据库

  • 任何一种编程语言或是框架都会提供对数据库进行操作的通用API

  • 各种数据库产品的厂商也会提供自身数据库产品针对常用语言的数据库驱动

  • Java亦是如此

  • Java提供了基础的数据访问接口JDBC,在此基础上,也衍生了一些功能更加强大的数据访问的第三方库或组件

常用的数据访问组件

  • JDBC:Java语言提供的最基础的数据访问

  • JdbcTemplate:Spring提供的数据操作组件,比JDBC操作更加方便

  • MyBatis:一个优秀的,也是最简单的持久层框架,可通过XML或注解来配置数据表与实体关系,灵活性高;但需要有一定的SQL语言基础

  • MyBatis-Plus:基于MyBatis的一款优秀的国产持久层框架,可免去SQL语句,完全面向对象

  • JPA(Java Persistence API):Java的一个持久层API,使用简单方便,不需要程序中使用SQL语句,有一套JPQL支持对象式的查询相关操作

  • Hibernate实现了JPA,并提供了;提供标准的ORM处理;且具有移植性好、提供缓存、HQL等特点,使用简单

实例数据E-R图

  • 下图是本章及后续业务会讲解的数据的E-R(Entity-Relationship)图(非标准图)

  • 其中,id都为int型,自增;所有表都具有的create_bycreate_timeupdate_byupdate_time字段

    实例数据E-R图

JDBC【扩展】

概述

  • Java数据库连接(Java Database Connectivity),是Java API重要的组成部分,是应用程序与数据库之间的桥梁

  • 提供了一组接口,提供给不同的数据库产品实现

  • 不同的数据库产品根据JDBC的接口,提供不同版本的 JDBC驱动

  • Java语言中,使用相应数据库产品的驱动,就能连接指定数据库进行数据操作

  • JDBC连接示意图如下

    JDBC连接示意图

主要对象

  • DriverManager:驱动管理,负责创建数据库连接

  • Connection:数据库连接,负责打开/关闭数据库连接,并负责创建Statement

  • Statement:数据处理,负责对数据库的查询、新增、修改、删除等操作

  • PreparedStatement,多次使用时,会先将SQL语句提交到数据库做预处理,多次使用能提高效率,支持?变量形式,避免SQL注入问题,相比Statement安全

  • ResultSet:查询结果集,提供对返回结果集的一系列操作,能够遍历获取数据表数据,提供了next、getString、getInt等方法获取数据

数据类型映射

  • Java中有自身的基本数据类型和常用的引用数据类型,如String、日期类

  • 每个数据库产品中,也有自身的数据类型,各不相同,也与Java中有一定的差异,如MySQL、Oracle等

  • Java程序中处理时需要与数据库中数据类型进行映射

  • 下面列出了Java与MySQL中的类型映射关系

    Java类型与MySQL类型映射

使用步骤

  1. 引入依赖,在pom.xml中添加对mysql-connector-java的依赖

    <!-- 连接MySQL数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
  2. 添加配置,在项目配置文件application.properties中添加JDBC连接配置

    #jdbc连接配置
    jdbc.url=jdbc:mysql://127.0.0.1:3306/springboot
    jdbc.driver-class-name=com.mysql.cj.jdbc.Driver
    jdbc.username=root
    jdbc.password=root
  3. 定义实体类,在演示项目entity包下添加与数据库表匹配的实体类

  4. 使用JDBC,在演示项目repository下实现数据库的访问

JdbTemplate【扩展】

概述

  • Spring在数据库的操作上,对JDBC做了再次的封装,即JdbcTemplate

  • 同时,可以配置默认的HikariCP数据库连接池参数

连接池【扩展】

  • 连接的频繁创建与销毁,是有很大的开销的,于是就有了连接池

  • 连接池主要作用

    • 限制总量,连接本身比较耗费资源,且过多容易导致数据库可用性差,让超过限制问题的连接等待

    • 复用,预先创建一定量的数据库连接,需要时直接使用,降低创建、销毁频率,提高数据库连接利用率

  • JDBC有一个标准的连接池接口javax.sql.DataSource,实现该接口的产品,即可快速接入

  • 业界提供了一系列的连接池实现技术

    • HikariCP(Spring Boot默认连接池)

    • Druid

    • C3P0

    • BoneCP

使用步骤

  1. 引入依赖,在pom.xml中添加对spring-boot-starter-jdbc、mysql-connector-java的依赖

    <!-- 连接MySQL数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
    ​
    <!-- jdbcTemplate需要的依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
  2. 添加配置,在项目配置文件application.properties中添加JdbcTemplate数据库连接配置和HikariCP连接池配置

    #JdbcTemplate配置,并且适用所有后续的数据库连接方式,像MyBatis等
    spring.datasource.url=jdbc:mysql://localhost:3306/springboot
    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    ​
    #hikariCP连接池配置
    spring.datasource.type=com.zaxxer.hikari.HikariDataSource
    spring.datasource.hikari.minimum-idle=5
    spring.datasource.hikari.maximum-pool-size=15
    spring.datasource.hikari.auto-commit=true
    spring.datasource.hikari.idle-timeout=30000
    spring.datasource.hikari.pool-name=MyHikariCP
    spring.datasource.hikari.max-lifetime=1800000
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.connection-test-query=SELECT 1
  3. 配置日志,在项目配置文件application.properties中添加SQL语句debug日志信息输出,【可选】

    #JdbcTemplate日志配置
    logging.level.org.springframework.jdbc.core.JdbcTemplate=debug
  4. 定义实体类,在演示项目entity包下添加与数据库表匹配的实体类

  5. 使用JdbcTemplate,在需要使用的地方自动装配JdbcTemplate使用,并将操作数据与实体类进行手动映射,具体见演示项目的repository包下

注意:日期格式在application.properties中配置

MyBatis【扩展】

概述

  • MyBatis是一款优秀的持久层框架,支持自定义SQL、存储过程以及高级映射

  • MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作

  • MyBatis可以通过简单的XML配置注解配置,将Java POJO( Plain Ordinary Java Object / Pure Old Java Object ,普通老式 Java 对象)映射为数据库中的记录

  • 现在指的是MyBatis 3,具体使用方式,参考官网文档:https://mybatis.org/mybatis-3/zh/index.html

XML方式

概述
  • 传统的MyBatis使用方式,多使用XML配置进行

  • 相对来说,这种方式稍显复杂,且没有结构化语法支持,出现问题也不容易排查

使用步骤
  1. 引入依赖,在pom.xml中添加对mysql-connector-java、mybatis-spring-boot-starter的依赖

    <!-- 连接MySQL数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>
  2. 添加配置,在项目配置文件application.properties中添加MyBatis相关配置数据库连接配置和HikariCP连接池配置,其中比较重要的是与@Mapper注解的接口关联的xml路径配置

    #数据库连接配置
    spring.datasource.url=jdbc:mysql://localhost:3306/springboot
    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    ​
    #mybatis配置
    #扫描的xml
    mybatis.mapper-locations=classpath:mapper/*.xml
    #xml配置中的type的基础包包
    mybatis.type-aliases-package=com.example.entity
    #mysql的下划线转驼峰,如数据库字段create_time映射到实体类的createTime
    mybatis.configuration.map-underscore-to-camel-case=true
    #mybatis日志配置
    logging.level.com.example.mapper=debug
    #是否开启二级缓存
    #mybatis.configuration.cache-enabled=true
    ​
    #hikariCP连接池配置
    #连接池类型
    spring.datasource.type=com.zaxxer.hikari.HikariDataSource
    #最小空闲连接
    spring.datasource.hikari.minimum-idle=5
    #最大连接数
    spring.datasource.hikari.maximum-pool-size=15
    #连接池返回的连接自动提交
    spring.datasource.hikari.auto-commit=true
    #空闲连接超时时间,默认值600000(10分钟)
    spring.datasource.hikari.idle-timeout=30000
    #连接池名称
    spring.datasource.hikari.pool-name=MyHikariCP
    #连接最大存活时间
    spring.datasource.hikari.max-lifetime=1800000
    #连接超时时间
    spring.datasource.hikari.connection-timeout=30000
    #测试连接是否可用的查询语句
    spring.datasource.hikari.connection-test-query=SELECT 1
  3. 配置日志,也可以添加SQL语句debug日志信息输出,使用logging.level.mapper所在包=debug使用,见上述代码中的配置,【可选】;注意,生产环境一般不输出此日志

  4. 定义实体类,在entity包下添加与数据库表匹配的实体类;注意,实体类的属性一般需要与数据库表的字段名相一致,一般实体类属性使用小驼峰,数据库表的字段使用划线,如属性createBy对应表的create_by字段

  5. 定义Mapper接口,在mapper包下添加对应数据表的Mapper接口及数据操作方法,并给接口添加@Mapper注解,将会自动注入Spring容器

  6. 添加XML配置,针对定义的Mapper接口,添加标准的XML配置,需要指定XML配置存放目录(一般是在resources\mapper目录,并在application.properties中通过mybatis.mapper-locations指向该配置目录下的*.xml文件);同时,在XML配置中,添加针对Mapper接口中数据操作方法匹配的SQL语句;相当于定义了Mapper接口的实现类;具体的模板如下(如果没有,可以自行添加,在Settings菜单下的Editor->File and Code Templates下添加)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="">
    </mapper>

     

  7. 使用MyBatis,在相应的服务中,就可以直接装配使用定义的Mapper接口,并使用其数据操作方法执行数据操作

注解方式

概述
  • 基于XML配置的复杂性和没有结构化语法支持,注解方式更容易被接受

  • 注解方式与XML方式类似

使用步骤
  • 与XML配置方式类似,只是将使用XML配置,替换成了在Mapper上使用@Select、@Insert、@Update、@Delete等注解完成

动态SQL【扩展】

概述
  • XML方式支持if、foreach、choosen(when、otherwise)、trim(where、set)等动态SQL支持

  • 注解方式,使用Provider形式提供支持

#和$
  • #

    • 预编译,能防止SQL注入,自动添加‘’

    • 主要用于对应字段的数据值

    • 尽量使用#

  • $

    • 语句拼接,会有SQL注入风险,不会自动添加’’

    • 主要用于动态表名、Order By列、分页数据,使用时字符串要使用’${xxx}’格式

关联查询
  • 一对一:XML方式使用多表association语法或join语法;注解方式使用@One注解

  • 一对多:XML方式使用多表collection语法或join语法;注解方式使用@Many注解

  • 多对多:一般会拆成不同方向的一对多处理

缓存【扩展】

  • MyBatis内置了一个强大的事务性查询缓存机制,分为一级缓存和二级缓存,第一次查询时,会将数据缓存起来,再次查询,数据将从缓存中获取;当然,如果中间有新增、更新、删除等操作,缓存将失效

  • 一级缓存,基于同一次请求的SqlSession,如果这个过程中一个相同的查询会执行多次,可以在相应的服务入口方法添加@Transactional注解,会启用一级缓存,提高查询效率

  • 二级缓存,基于同一个namespace,也即同一个Mapper的缓存,在配置文件中添加<cache />(注解形式添加@CacheNamespace(blocking = true)注解),可启用二级缓存

  • 注意,如果是分布式的多节点部署,则不要开启一级缓存、二级缓存;直接使用第三方的Redis、Memcached等第三方缓存

  • 详细介绍MyBatis站点:https://mybatis.org/mybatis-3/zh/index.html

Spring事务

  • Spring Boot中提供了事务处理机制针对各种数据访问技术 ,如JdbcTemplate、MyBatis、MyBatis Plus等,分声明式事务和编程式事务

  • 声明式事务掌握

    • 基于AOP

    • 使用注解@Transactional标注在public修饰的方法上

    • 特点:使用简单,但整个注解方法持续占用当前Connection,直到方法结束才释放Connection,效率相对相低

  • 编程式事务,了解【扩展】

    • 使用TransactionTemplate、TransactionCallback、TransactionStatus组合完成,底层使用的是PlatformTransactionManager类

    • 特点:控制粒度更小,比声明式复杂,但可以控制只在TransactionTemplate.execute()方法中使用Connection,对于一些业务中具有事务特性,但也参杂大量数据查询、IO非事务特性场景,可考虑使用编程式事务

  • 注意:在其他的数据访问组合中,可以使用相同机制使用Spring事务

MyBatis-Plus

概述

  • 润物无声:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 效率至上:只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间

  • 丰富功能:代码生成、物理分页、性能分析等功能一应俱全

  • 最重要特点:基于MyBatis,但去除掉了MyBatis对于SQL语句的依赖,使用更简单

使用步骤

  1. 引入依赖:MyBatis Plus需要的依赖包mysql-connector-java、mybatis-plus-boot-starter

    <!-- 连接MySQL数据库 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
    <!--MyBatis-Plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>
  2. 添加配置:与MyBatis相同,在项目配置文件application.properties中添加MyBatis相关配置数据库连接配置和HikariCP连接池配置;与MyBatis相同

  3. 定义实体类

    1. 表名映射:在与表对应的实体类上添加@TableName("表名")

    2. 主键属性:添加@TableId(type= IdType.AUTO)

    3. 普通属性:如果实体类属性与数据库中字段名不同,可添加 @TableField(value = "列名")进行映射

  4. 定义Mapper:针对实体,定义Mapper接口,并继承BaseMapper<实体类>;如下面就是用户的Mapper

    package com.example.mapper;
    ​
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.example.entity.UserEntity;
    ​
    public interface UserMapper extends BaseMapper<UserEntity> {
    }
  5. 添加@MapperScan注解:在配置类或启动类添加@MapperScan(mapper包),扫描指定mapper包下的所有继承于BaseMapper的类

    -------------------------------------------------此时,就可以使用Mapper进行数据访问,但方法不够丰富-------------------------------------------------

  6. 定义Service:针对实体,定义Service接口,并继承IService<实体类>;针对实体,定义Service接口实现,并继承服务接口与ServiceImpl<映射Mapper,实体类>,此时,在Service实现中,可使用ServiceImpl的众多对Mapper的封装方法;提供了一系列的便利操作,【可选】

  7. 分页,需要返回一个指定数据库类型的分页配置MybatisPlusInterceptor对象,因为不同的数据库类型分布逻辑并不相同(如SQL Server是top xxx,My SQL是limit),见config\MybatisPlusConfig类

  8. 使用MyBatis-Plus,在相应的服务中,可直接使用Mapper,也可直接使用Service

多层结构中的问题

问题一

  • 新增/修改时,需要调用方提供创建人/修改人和时间信息吗?新增/修改时,需要调用方提供主键ID吗?

  • 返回响应信息时,需要包含密码么?

  • 返回基础字典数据作为前端页面中的被选择项时,需要返回创建人/修改人和时间等信息么?

问题二

  • 登录时,如果不成功,可能返回[用户名不存在]、[密码错误]、[密码次数超限]不同形式的错误提示信息;如果成功,则返回用户及相关详细信息,两者结构不同,接口使用者如何方便判断、兼容?

  • 如果返回时不仅需要返回数据集合,还需要有如分布的汇总等信息输出,如何兼容?

DTO

  • 数据传输对象(Data Transfer Object),用于项目各个层次数据传输,主要针对Service、Controller层接收和返回的都应该是DTO,是面向对象的

  • 有了DTO后,entity将会专注于与数据表一对一映射

  • DTO可能是多个entity属性的组合,也可能是某个entity的一部分属性,重点是呈现接口需要的输入/输出数据,不包含一些接口无关的数据,比如查询时的密码、保存时的创建时间和更新时间等

  • DTO应用目的:让接口或服务,只接收需要的输入,只返回必需的输出

  • 解决上述问题一

请求封装和响应封装

请求封装
  • 一般会兼容比较丰富的请求数据,不做过多封装,一般是Java包装类、DTO,分页请求除外

  • 一般的项目,可以不对请求进行封装,直接使用DTO即可

响应封装
  • 一般会封装成标准格式,并提供一些便利操作方法,标准格式包括code、message、data、total等

  • 一个项目,必须有一个标准的响应封装,甚至一个团队所有的项目保持相同的响应封装,给外部提供的服务接口更易读

  • 响应封装应用目的:提供标准的响应,让调用方法处理更简单

  • 解决上述问题二

对象映射

概述
  • 由于引入了DTO,就存在比较频繁的DTO与Entity之间的对象相互赋值,逐个属性的getter和setter赋值相对代码比较麻烦

  • 可使用Spring中的BeanUtils进行映射,也可以使用第三方的工具

  • ModelMapper能够实现具有相同属性的对象间的属性值自动映射

使用步骤
  • 引入依赖,在pom.xml中引入modelmapper-jackson依赖

    <!-- 基于jackson的对象映射 -->
    <dependency>
        <groupId>org.modelmapper.extensions</groupId>
        <artifactId>modelmapper-jackson</artifactId>
        <version>2.4.5</version>
    </dependency>
  • 将ModelMapper注入Spring容器,通过添加一个配置类实现

    package com.example.config;
    ​
    import org.modelmapper.ModelMapper;
    import org.modelmapper.convention.MatchingStrategies;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    ​
    /**
     * 对象映射工具Bean
     */
    @Configuration
    public class ModelMapperConfig {
        @Bean
        public ModelMapper modelMapper() {
            ModelMapper modelMapper = new ModelMapper();
            //设置映射时匹配策略
            //Standard表示标准匹配策略,为默认选项
            //Loose表示松散匹配策略
            //Strict表示严格匹配策略
            modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
            return modelMapper;
        }
    }
  • 自动装配使用,需要的类中装配就好,也可以直接new ModelMapper使用;如下面的代码返回一个

    UserOutputDto userOutputDto = modelMapper.map(userEntity, UserOutputDto.class);

领域驱动设计(Domain-Driven Design)【扩展】

概述
  • 主要是由领域专家、业务人员、技术人员组合一起进行业务建模的一种设计方式

  • 并构建出一个大家都能接受的业务模型,勾勒出产品全貌,最后交付可接收的产品

  • 涉及到很多概念,可扩展学习

各种Object封装的特点
  • VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来

  • DTO(Data Transfer Object):数据传输对象,这个概念最早来源于J2EE,泛指用于展示层与服务层之间的数据传输对象

  • DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体,会是多个PO的组合

  • PO(Persistent Object):持久化对象,也就是Entity,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系

     

    各种Object的关系(图片来自网络)
实例项目中的DTO与Entity
  • 具体见附件的springboot-data-mybatis-plus项目

实例项目中的DTO与Entity关系

数据验证

概述
  • 在实际的项目中,接口对于请求参数是要进行一定的合理性验证

  • 常用的验证有两种处理方式

    • 通用性验证,可借助第三方组件(如Spring Boot Validation)进行,验证通常包括非空,长度,格式化等

    • 业务性验证,一般需要手写代码实现

Spring Boot Validation
  • 提供了一系列注解来对需要验证的Dto进行验证标识,如@NotNull、@Length、@Min、@Max等

  • 底层依赖hibernate-validator

Spring Boot Validation使用步骤

  1. 添加依赖:在pom中引入spring-boot-starter-validation

    <!-- 【通用验证】1、添加依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
  2. 添加通用异常处理:添加ControllerAdvice针对BindException数据绑定异常的通用处理,代码片断如下

    package com.example.advice;
    ​
    import com.example.dto.common.ResponseData;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.BindException;
    import org.springframework.validation.FieldError;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    ​
    @ControllerAdvice
    public class GlobalExceptionHandler {
        @Autowired
        ObjectMapper objectMapper;
    ​
        /**
         * 【通用验证】1、添加依赖
         * 拦截BindException,所有的验证框架spring-boot-starter-validation里的注解如果不符合规则都会抛出此异常
         * @param ex
         * @throws IOException
         */
        @ExceptionHandler(BindException.class)
        @ResponseBody
        public ResponseData handleBindException(BindException ex) {
            //获取错误信息
            List<FieldError> fieldErrors = ex.getFieldErrors();
            List<String> errors = new ArrayList<>();
            fieldErrors.stream().forEach(s->{
                errors.add(s.getDefaultMessage());
            });
    ​
            //构建标准响应
            ResponseData responseData = new ResponseData();
            responseData.setCode(996);
            responseData.setMessage(errors.stream().collect(Collectors.joining(",")));
    ​
            return responseData;
        }
    }
  3. 输入DTO添加验证注解:在接口请求参数的DTO上添加相应验证注解,代码片断如下

    package com.example.dto.input.user;
    ​
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    import org.hibernate.validator.constraints.Length;
    ​
    import javax.validation.constraints.NotNull;
    ​
    /**
     * 用户创建传入DTO
     */
    @ApiModel(value = "用户创建传入DTO",description = "用户创建传入信息DTO")
    @Data
    public class UserCreateInputDto {
        //【通用验证】3、输入DTO添加验证注解
        @ApiModelProperty(value = "用户名")
        @NotNull(message = "用户名不能为空")
        @Length(min = 2,max = 20,message = "用户名长度必须在2-20个字符之间")
        private String username;
    ​
        //【通用验证】3、输入DTO添加验证注解
        @ApiModelProperty(value = "密码")
        @NotNull(message = "密码不能为空")
        @Length(min = 6,max = 20,message = "密码长度必须在6-50个字符之间")
        private String password;
    ​
        //【通用验证】3、输入DTO添加验证注解
        @ApiModelProperty(value = "姓名")
        @NotNull(message = "姓名不能为空")
        @Length(min = 4,max = 20,message = "姓名长度必须在4-50个字符之间")
        private String name;
    ​
        @ApiModelProperty(value = "描述")
        private String description;
    ​
    }
  4. HTTP请求接口添加@Validated注解:在Controller接口请求参数DTO前添加@Validated注解,代码片断如下

    /**
    * 【通用验证】4、HTTP请求接口添加@Validated注解
    * @param inputDto
    * @return
    */
    @ApiOperation(value = "创建",notes = "创建一条新数据")
    @PostMapping("/")
    ResponseData create(@RequestBody @Validated UserCreateInputDto inputDto){
       return userService.create(inputDto);
    }
  5. 生效,将会自动拦截生效

MyBatis-Plus的其他功能

自动填充

概述
  • 对于一些基础的数据,是要根据数据产生的上下文自动产生的,如创建某条数据时的创建人、创建时间,多租户的租户信息等

  • MyBatis-Plus中使用MetaObjectHandler接口,并配合@TableField注解实现自动填充

使用步骤
  1. 添加拦截

    • 添加MetaObjectHandler接口实现,并重写insertFill、updateFill方法

    • 在方法中,使用登录时保存在Session中的登录人信息,填充创建人、更新人信息

    • 在方法中,使用当前时间,设置创建时间、更新时间

  2. 关联到实体类

    • 创建人/创建时间拦截,在实体类使用@TableField(fill = FieldFill.INSERT)注解实现拦截

    • 更新人/更新时间拦截,在实体类使用@TableField(fill =FieldFill.INSERT_UPDATE)注解实现拦截

多数据源【扩展】

概述
  • MyBatis-Plus中,能方法的支持多数据源

使用步骤
  1. 引入依赖:MyBatis-plus需要的依赖包mysql-connector-java、 mybatis-plus-boot-starter、 dynamic-datasource-spring-boot-starter

  2. 在application.properties中添加数据库连接和相应配置

  3. 其他Entity、Mapper、Service同单数据源

  4. 在Service上添加@DS(“数据源”)使用指定的数据源即可

JPA【扩展】

概述

  • 除了上述的数据访问方式,Spring Boot中还集成了JPA

  • Java持久层API(Java Persistence API),提供了一套标准的ORM规范,目标是让开发人员少写或不写SQL语句,主要实现产品有Hibernate、TopLink、Eclipselink等

  • 特点:简单易用,集成方便,支持面向对象的特性,提供独特的JPQL查询语言

  • 底层使用的是Hibernate

使用方式

  1. 引入依赖,JPA需要的依赖包mysql-connector-java、 spring-boot-starter-data-jpa

  2. 添加配置,在application.properties中添加数据库连接和相应配置

  3. 定义实体类

    • 表名映射:在与表对应的实体类上添加@Table(“表名”)、@Entity

    • 主键属性:添加@Id、@GeneratedValue(strategy=GenerationType.IDENTITY)

    • 普通属性:如果与数据库中列名不同,可添加 @Column(value = "列名")进行映射

  4. 定义Repository,针对实体,定义Repository接口,并继承JpaRepository<实体类, 主键类型> ,此时,Repository就可以用于做数据访问

此外,在定义的Repository接口中,还提供了findByXXX声明式的查询

注意

注意

项目比较多,争取掌握springboot-data-mybatis-plus项目的数据访问、DTO、ResponseData封装、对象映射、自动填充

代码

网盘地址:链接:https://pan.baidu.com/s/18DaKpTTx9T__XG8jkv3naw?pwd=8888

posted @ 2024-05-30 22:51  拐子  阅读(101)  评论(0编辑  收藏  举报