SpringBoot框架学习笔记(九):数据库操作(JDBC+HikariDataSource、整合 Druid 、 Mybatis 以及 Mybatis-plus 到SpringBoot)

1 JDBC+HikariDataSource

1.1 介绍

HikariDataSource 是目前市面上非常优秀的数据源,是springboot2默认数据源

1.2 应用实例

1.2.1 需求

演示SpringBoot如何通过JDBC+HikariDataSource完成对mysql操作

1.2.2 代码实现

(1)准备数据库初始数据

 # 创建数据库
 DROP DATABASE IF EXISTS spring_boot; 
 CREATE DATABASE spring_boot; 
 USE spring_boot;
 # 创建家居表
 CREATE TABLE furn(
 `id` INT(11) PRIMARY KEY AUTO_INCREMENT,##id
 `name` VARCHAR(64) NOT NULL,##家居名
 `maker` VARCHAR(64) NOT NULL,##厂商
 `price` DECIMAL(11,2) NOT NULL,##价格
 `sales` INT(11) NOT NULL,##销量
 `stock` INT(11) NOT NULL,##库存
 `img_path` VARCHAR(256) NOT NULL ##照片路径 
 );
 # 初始化家居数据
 INSERT INTO furn(`id`,`name`,`maker`,`price`,`sales`,`stock`,`img_path`) VALUES
 (NULL,'北欧风格小桌子','熊猫家居',180,666,7,'assets/images/product-image/1.jpg'),
 (NULL,'简约风格小椅子','熊猫家居',180,666,7, 'assets/images/product-image/2.jpg'),
 (NULL,'典雅风格小台灯','蚂蚁家居',180,666,7,'assets/images/product-image/3.jpg'),
 (NULL,'温馨风格盆景架','蚂蚁家居',180,666,7,'assets/images/product-image/4.jpg');
  
SELECT * FROM furn;

准备对应实体类

package org.wwj.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Furn {
    private Integer id;
    private String name;
    private BigDecimal price;
    private Integer sales;
    private Integer stock;
    private String imgPath = "assets/images/product-image/1.jpg";
}

 (2)进行数据库开发,在pom.xml 引入data-jdbc starter,该依赖中包含了JDBC和Hikari数据源

<!--引入data-jdbc starter-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

(3)Spring Boot 不知道项目要操作Mysql还是Oracle,需要在pom.xml 指定导入数据库驱动,并指定对应版本 

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version>
</dependency>

(4)引入 test start

<!--如果要开发springboot测试类,需要引入 test starter-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>

 (5)在application.yml 配置操作数据源的信息

spring:
  datasource: # 配置数据源
    url: jdbc:mysql://localhost:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

(6)在test目录下创建测试类 ApplicationTests.java 进行测试

package org.wwj.springboot;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.wwj.bean.Furn;

import javax.annotation.Resource;
import java.util.List;

@SpringBootTest
public class ApplicationTests {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Test
    public void contextLoads(){
        RowMapper<Furn> rowMapper = new BeanPropertyRowMapper<>(Furn.class);
        String sql = "SELECT * FROM furn";
        List<Furn> furns = jdbcTemplate.query(sql, rowMapper);
        for (Furn furn :furns) {
            System.out.println(furn);
        }
        // 输出数据源类型
        System.out.println(jdbcTemplate.getDataSource().getClass());

    }
}

1.2.3 测试结果

2 整合 Druid 到SpringBoot

2.1 基本介绍

(1)官方文档:

使用手册:GitHub - alibaba/druid: 阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池

中文手册:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98 

(2)Druid:性能优秀,Druid提供性能卓越的连接池功能外,还集成了SQL监控,黑名单拦截等功能,强大的监控特性,通过Druid提供的监控功能,可以清楚知道连接池和SQL的工作情况,所以根据项目需要,也要掌握Druid和SpringBoot整合

(3)整合 Druid 到SpringBoot有两种方式

  • 自定义方式
  • 引入starter方式

2.2 Durid基本使用

需求说明:将 Spring-Boot 的数据源切换成 Druid

代码实现:

(1)修改pom.xml,引入druid依赖

<!--引入druid依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.17</version>
</dependency>

(2)创建配置类 DruidDataSourceConfig.java,进行如下配置后,即可成功将数据源切换为Druid

package org.wwj.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DruidDataSourceConfig {

    // 编写方法,注入DruidDataSource
    @ConfigurationProperties("spring.datasource")
    @Bean
    public DruidDataSource dataSource(){
        // 配置了@ConfigurationProperties("spring.datasource")
        // 就可以读取到application.yml的配置
        // 这样就不需要调用DruidDataSource对象的set方法给属性赋值,会自动关联
        return new DruidDataSource();
    }
}

问题:为什么我们注入自己的DataSource,默认的HiKariDatasource就失效了?

解读:在springboot底层会判断容器中是否有DataSource Bean,如果有就不注入默认的 HiKari

2.3 Durid监控功能-sql监控

2.3.1 SQL监控数据

修改配置类 DruidDataSourceConfig.java,增加druid监控功能

文档地址:常见问题 · alibaba/druid Wiki · GitHub 

2.3.2 SQL监控数据-测试页面

(1)修改配置类  DruidDataSourceConfig.java,配置druid的监控页功能

//配置druid的监控页功能
@Bean
public ServletRegistrationBean statViewServlet() {
    // 创建  StatViewServlet
    StatViewServlet statViewServlet = new StatViewServlet();
    ServletRegistrationBean<StatViewServlet> registrationBean =
            new ServletRegistrationBean<>(statViewServlet, "/druid/*");

    // 设置参数
    HashMap<String, String> map = new HashMap<>();
    // 设置用户名
    map.put("loginUsername","wwj");
    // 设置密码
    map.put("loginPassword","123456");
    registrationBean.setInitParameters(map);

    return registrationBean;
}

这样就配置好了,启动项目,浏览器输入 localhost:9999/druid 即可进入监控页面

(2) 修改配置类  DruidDataSourceConfig.java 中的 dataSource()方法,添加sql监控功能

// 编写方法,注入DruidDataSource
@ConfigurationProperties("spring.datasource")
@Bean
public DruidDataSource dataSource() throws SQLException {
    // 配置了@ConfigurationProperties("spring.datasource")
    // 就可以读取到application.yml的配置
    // 这样就不需要调用DruidDataSource对象的set方法给属性赋值,会自动关联
    DruidDataSource druidDataSource = new DruidDataSource();
    // 加入监控功能
    druidDataSource.setFilters("stat");
    return druidDataSource;
}

(3)创建 DruidSqlController.java,模拟操作DB的请求

package org.wwj.controller;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.wwj.bean.Furn;

import javax.annotation.Resource;
import java.util.List;

public class DruidSqlController {

    @Resource
    private JdbcTemplate jdbcTemplate;

    @ResponseBody
    @GetMapping("/sql")
    public List<Furn> crudDB() {
        String sql = "select * from furn";
        RowMapper<Furn> furnRowMapper = new BeanPropertyRowMapper<>();
        List<Furn> furns = jdbcTemplate.query(sql, furnRowMapper);
        return furns;
    }
}

(4)重新启动项目 ,浏览器输入 localhost:9999/sql 进行测试

sql监控页效果如下

 sql监控列含义:

2.4 Durid监控功能-Web关联监控

2.4.1 Web关联监控配置-Web应用、URI监控

//配置WebStatFilter,用于采集web-jdbc关联的监控数据
@Bean
public FilterRegistrationBean webStatFilter(){
    // 创建 WebStatFilter
    WebStatFilter webStatFilter = new WebStatFilter();
    FilterRegistrationBean<WebStatFilter> registrationBean =
            new FilterRegistrationBean<>(webStatFilter);
    // 对所有url进行监控
    registrationBean.setUrlPatterns(Arrays.asList("/*"));
    // 排除指定的url
    Map map = new HashMap<>();
    map.put("exclusions","*.js,*.gif,*.jpg,*.png");
    registrationBean.setInitParameters(map);
    return registrationBean;
}

2.4.2 web应用和URI监控页面

2.5 Durid监控功能-SQL防火墙

SQL防火墙防火强的配置很简单,只需要给filters参数增加一个值wall即可

修改配置类  DruidDataSourceConfig.java 中的 dataSource()方法,开启SQL防火墙

// 编写方法,注入DruidDataSource
@ConfigurationProperties("spring.datasource")
@Bean
public DruidDataSource dataSource() throws SQLException {
    // 配置了@ConfigurationProperties("spring.datasource")
    // 就可以读取到application.yml的配置
    // 这样就不需要调用DruidDataSource对象的set方法给属性赋值,会自动关联
    DruidDataSource druidDataSource = new DruidDataSource();
    // 加入监控功能,加入sql防火墙
    druidDataSource.setFilters("stat,wall");
    return druidDataSource;
}

2.6 Durid监控功能-Session监控

Session监控无需配置,自动开启(需要登录才能看到,登录地址:localhost9999:/druid/login.html)

 

2.7 Druid Spring Boot Starter

2.7.1 基本介绍

前面使用的是自己引入druid+配置类方式整合Druid和监控,即自定义方式。Druid Spring Boot Starter 可以让程序员在Spring Boot项目中更加轻松集成Druid监控

文档地址:druid/druid-spring-boot-starter at master · alibaba/druid · GitHub

2.7.2 代码实现

(1)修改pom.xml 注销druid的依赖

(2)注销 DruidDataSourceConfig.java

(3)修改pom.xml,引入 Druid Spring Boot Starter

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.17</version>
</dependency>

 (4)配置YML文件

spring:
  datasource: # 配置数据源
    url: jdbc:mysql://localhost:3306/spring_boot?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid的其他属性配置
    druid:
      stat-view-servlet:
        # 配置druid的监控页功能
        enabled: true
        # 用户名
        login-username: wwj
        # 密码
        login-password: 123456
        reset-enable: false
      # 配置web监控
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
      filter:
        stat: # 配置sql监控
          # 打开慢SQL记录
          slow-sql-millis: 1000
          log-slow-sql: true
          enabled: true
        wall: # 配置sql防火墙
          enabled: true
          config:
            # 把删除表操作拉入黑名单,即不允许执行删除表操作
            drop-table-allow: false
            # 不允许执行查询所有字段的sql
            select-all-column-allow: false

      # 也可以这样配置,stat: 监控统计、Slf4j:日志记录、waLL: 防御sqL注入
#      filters: stat,wall,slf4j
      # 初始化时建立物理连接的个数
      initial-size: 5
      # 连接池的最小空闲数量
      min-idle: 5
      # 连接池最大连接数量
      max-active: 20
      # 获取连接时最大等待时间,单位毫秒
      max-wait: 60000
      # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 既作为检测的间隔时间又作为testWhileIdel执行的依据
      time-between-eviction-runs-millis: 60000
      # 销毁线程时检测当前连接的最后活动时间和当前时间差大于该值时,关闭当前连接(配置连接在池中的最小生存时间)
      min-evictable-idle-time-millis: 30000
      # 用来检测数据库连接是否有效的sql 必须是一个查询语句(oracle中为 select 1 from dual)
      validation-query: select 'x'
      # 申请连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-borrow: false
      # 归还连接时会执行validationQuery检测连接是否有效,开启会降低性能,默认为true
      test-on-return: false
      # 是否缓存preparedStatement, 也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
      pool-prepared-statements: false
      # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      max-pool-prepared-statement-per-connection-size: -1
      # 合并多个DruidDataSource的监控数据
      use-global-data-source-stat: true

配置完成! 

3 整合 Mybatis 到SpringBoot

3.1 需求说明

将spring boot 和 mybatis 整合,查询出一条数据

3.2 综合案例

(1)在 pom.xml 文件中加入mybatis 依赖

<!--引入mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.1</version>
</dependency>

完整pom.xml文件如下 

<?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>org.wwj</groupId>
    <artifactId>springboot-mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <!-- 导入 springboot 父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <dependencies>

        <!--引入Thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <!-- 导入 web 项目场景启动器,会自动导入和 web 开发相关依赖 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>

        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--引入配置处理器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
        </dependency>

<!--        引入data-jdbc starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>

        <!--引入数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <!--如果要开发springboot测试类,需要引入 test starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <!--引入druid-spring-boot-starter-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

(2)数据库准备代码

 CREATE DATABASE`springboot_mybatis` ;
 USE`springboot_mybatis` ;
 CREATE TABLE`monster`(
 `id` INT NOT NULL AUTO_INCREMENT, 
 `age` INT NOT NULL,
 `birthday` DATE DEFAULT NULL,
 `email` VARCHAR(255)DEFAULT NULL, 
 `gender` CHAR(1) DEFAULT NULL,
 `name` VARCHAR(255)DEFAULT NULL, 
 `salary` DOUBLE NOT NULL, 
 PRIMARY KEY(`id`)
 )CHARSET=utf8;
 
SELECT*FROM`monster`;
INSERT INTO monster VALUES(NULL,20,'2000-11-11','nmw@sohu.com','男','牛魔王',5000.88);
INSERT INTO monster VALUES(NULL,10,'2011-11-11','bgj@sohu.com','女','白骨精',8000.88);
SELECT * FROM `monster` WHERE `id` = 1

对应数据库表中的实体类 Monster.java 如下

package org.wwj.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Date;


@NoArgsConstructor
@AllArgsConstructor
@Data
public class Monster {
    private Integer id;
    private Integer age;
    // 这里注意一定要导入 java.sql.Date 包里的 Date
    private Date birthday;
    private String email;
    private char gender;
    private String name;
    private Double salary;
}

(3)创建接口 MonsterMapper.java

在mapper接口使用@Mapper就会扫描,并将Mapper接口对象注入

也可以在主程序上添加@MapperScan(basePackage = {"包名"}),来扫描包下所有的mapper接口

package org.wwj.dao;

import org.apache.ibatis.annotations.Mapper;
import org.wwj.bean.Monster;

@Mapper
public interface MonsterMapper {

    //根据id查询妖怪
    Monster findMonsterById(Integer id);
}

(4) 在类路径(resources)下创建mapper目录,在该目录下创建 MonsterMapper.xml

<?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="org.wwj.dao.MonsterMapper">
    <select id="findMonsterById" parameterType="Integer" resultType="Monster">
        select * from `monster` where `id` = #{id}
    </select>
</mapper>

(5)配置 YAML 文件

spring:
  datasource: # 配置数据源
    url: jdbc:mysql://localhost:3306/springboot_mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
server:
  port: 9999

mybatis:
  # 指定要扫描的 XxxMapper.xml 文件
  mapper-locations: classpath:mapper/*.xml
  # 通过config-location,可以指定mybatis-config.xml,就可以用传统的方式来配置mybatis
#  config-location:
  #也可以直接在application.yml进行配置
  # 举例1,配置原来的 typeAliases
  type-aliases-package: org.wwj.bean
  # 举例2,配置mybatis自带的日志输出
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

 (5)创建测试类进行测试

package org.wwj.dao;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.wwj.bean.Monster;

import javax.annotation.Resource;

@SpringBootTest
public class MonsterMapperTest {

    @Resource
    private MonsterMapper monsterMapper;

    @Test
    public void findMonsterByIdTest(){
        Monster monster = monsterMapper.findMonsterById(1);
        System.out.println(monster);
    }
}

注意,需要创建springboot主程序,才能运行测试类

package org.wwj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;


@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ioc = SpringApplication.run(Application.class, args);
        System.out.println("hello");
    }
}

测试效果如下

3.3 注意事项和细节说明

如果看到 sql 打印的时间和数据库里面存储的时间不一样,这是因为时区问题。查看当前时区:SHOW VARIABLES LIKE '%time_zone%';

可通过两种方式解决: 

第一种:永久修改时区问题

找到路径中的 my.ini 配置文件,并打开它

在该文件的[mysqld]字段下面添加一行:default-time-zone='+08:00',保存即可。下次再重启MySQL时,时区仍为东八区,不会还原。 

第二种:在需要转换时间的类中添加注解 @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)

//GMT 就是格林尼治标准时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date birthday;

4 整合 Mybatis-plus 到SpringBoot

4.1 基本介绍

(1)官方文档地址:MyBatis-Plus 🚀 为简化开发而生

(2)MyBatis-Plus(简称MP) 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

(3)强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

4.2 整合 Mybatis-plus 实例

4.2.1 环境准备

(1)新建一个项目,导入依赖

  将springboot 整合mybatis的依赖替换为整合mybatis-plus的起步依赖;

<!--引入mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

IDEA按照一个插件Maven Helper可以查看是否有依赖冲突。 

(2)修改yaml配置文件

端口、数据库、mybatis-plus日志输出、驼峰映射、xml位置等 

spring:
  datasource: # 配置数据源
    url: jdbc:mysql://localhost:3306/springboot_mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
server:
  port: 9999

mybatis-plus:
  # 扫描包
  mapper-locations: mapper/*.xml
  configuration:
    # 配置日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
  # 别名设置
  type-aliases-package: com.wwj.bean

(3)Monster实体类,绑定表名、主键名 

package org.wwj.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.Date;


@NoArgsConstructor
@AllArgsConstructor
@Data
//指定表名,若一致可以不用指定
@TableName(value = "monster")
public class Monster {
    //指定主键名、主键生产策略
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    //指定列名,若一致可以不用指定
    @TableField(value = "age")
    private Integer age;
    // 这里注意一定要导入 java.sql.Date 包里的 Date
    private Date birthday;
    private String email;
    private Character gender;
    private String name;
    private Double salary;
}

(4)MonsterMapper

 只要继承BaseMapper<~>即可、其他方法和xml可以删掉。如果BaseMapper提供的方法不能满足业务需求时就可以自己定义

@Mapper
public interface MonsterMapper extends BaseMapper<Monster> {}

 MonsterMapper继承BaseMapper<~>后就可以不用编写XML来实现了 

(5)MonsterService 

在mybatis-plus中,service 层接口继承 Iservice<~> 接口 

public interface MonsterService extends IService<Monster> {}

service 实现类,需要继承 ServiceImpl<~> 

/**
 * 因为 ServiceImpl 类实现了 IService 接口
 * MonsterService 接口又继承 IService 接口
 * 这里 MonsterServiceImpl 继承了 ServiceImpl 就可以认为是实现了 MonsterService
 */
@Service
public class MonsterServiceImpl
        extends ServiceImpl<MonsterMapper, Monster>
        implements MonsterService{
}

(6)MonsterController

package org.wwj.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.wwj.bean.Monster;
import org.wwj.service.MonsterService;

import javax.annotation.Resource;

@Controller
public class MonsterController {
    
    @Resource
    private MonsterService monsterService;
    
    //根据id返回对应的monster
    @GetMapping("/monster")
    @ResponseBody
    public Monster getMonsterById(@RequestParam("id") Integer id){
        return monsterService.getById(id);
    }
}

4.2.2 使用

本文直接在测试类中注入IUserMapper、编写测试方法进行测试。service层、controller层就不写了

@Resource
private MonsterMapper monsterMapper;

可以看到,自己并没有新建方法,而userMapper可以调用BaseMapper提供的众多方法。

可以看到BaseMapper提供的方法需要的参数有字符串、实体类、map、条件构造器等。下文将使用一些用例来测试这些方法。为了增加观感、只展示如何使用、执行结果、SQL日志就不截图占用篇幅了。

4.2.2.1 基础增删改查

(1)新增一条Monster数据

@Test
public void insert(){
    Monster monster =
            new Monster(3, 14, new Date(323123), "nmw@hhh.com", '男', "牛魔王", 5000.88);
    monsterMapper.insert(monster);
}

(2)根据条件删除Monster

根据ID删除

@Test
public void deleteById(){
    monsterMapper.deleteById(3);
}

 根据某列精准匹配删除 

@Test
public void deleteByMap(){
    Map<String, Object> map = new HashMap<>();
    map.put("email", "nmw@hhh.com");
    monsterMapper.deleteByMap(map);
}

(3)修改数据Monster信息

根据ID修改 

@Test
public void updateById(){
    Monster monster = new Monster();
    monster.setId(2);
    monster.setAge(15);
    monster.setGender('男');
    monsterMapper.updateById(monster);
}

 (4)根据条件查询Monster

查询全部用户 

@Test
public void findAllMonster(){
    // 第一种方式
    List<Monster> monsters1 = monsterMapper.selectByMap(null);
    System.out.println(monsters1);
    // 第二种方式
    List<Monster> monsters2 = monsterMapper.selectList(null);
    System.out.println(monsters2);
}

 根据ID查询 

@Test
public void findMonsterById(){
    Monster monster = monsterMapper.selectById(1);
    System.out.println(monster);
}

 根据某列精确匹配 

@Test
public void findMonsterByMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("age", 15);
    List<Monster> monsters = monsterMapper.selectByMap(map);
    System.out.println(monsters);

}
4.2.2.2 批量操作

(1)批量新增

@Test
public void batchInsert(){
    Monster monster1 = new Monster(
            null, 14, new Date(13231230), "1nmw@hhh.com", '男', "牛魔王1", 15000.88);
    Monster monster2 = new Monster(
            null, 15, new Date(23231230), "2nmw@hhh.com", '男', "牛魔王2", 25000.88);
    Monster monster3 = new Monster(
            null, 16, new Date(33231230), "3nmw@hhh.com", '男', "牛魔王3", 35000.88);

    ArrayList<Monster> list = new ArrayList<>();
    list.add(monster1);
    list.add(monster2);
    list.add(monster3);

    list.forEach(monster -> {
        monsterMapper.insert(monster);
    });

}

(2)批量删除

@Test
public void batchDelete(){
    ArrayList<Integer> ids = new ArrayList<>();
    ids.add(5);
    ids.add(6);
    ids.add(7);
    monsterMapper.deleteBatchIds(ids);
}

 (3)批量查询

@Test
public void batchSelect(){
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    List<Monster> monsters = monsterMapper.selectBatchIds(list);
}
4.2.2.3 查询条件构造器【QueryWrapper】使用

条件构造器就是通过链式编程的形式构造where后面的SQL可选项有

比如查询 age>=14 and name like "%牛魔王%"

@Test
public void selectListByQueryWrapper(){
    QueryWrapper<Monster> queryWrapper = new QueryWrapper<>();
    queryWrapper.ge("age", 14)
                    .like("name","牛魔王");
    monsterMapper.selectList(queryWrapper);

}

但是存在许多硬编码。 

4.2.2.4 修改条件构造器【UpdateWrapper】造器使用

也是通过链式编程的方式拼接修改条件; 

比如,将怪物名字为牛魔王的年龄修改为20

@Test
public void updateByUpdateWrapper(){
    UpdateWrapper<Monster> wrapper = new UpdateWrapper<>();

    wrapper.eq("name","牛魔王")
            .set("age", 20);
    Monster monster = new Monster();
    monsterMapper.update(monster, wrapper);
}

也是存在字段的硬编码 

4.2.3 减少硬编码

【LambdaQueryWrapper】来减少硬编码、直接通过类获取属性的方式得到字段

比如查询名字有"牛"的所有妖怪

@Test
public void updateByLambdaQueryWrapper(){
    LambdaQueryWrapper<Monster> wrapper = new LambdaQueryWrapper<>();

    wrapper.like(Monster::getName,"牛");

    List<Monster> monsters = monsterMapper.selectList(wrapper);
}

【LambdaUpdateWrapper】减少硬编码,将名字有"王"的所有妖怪性别改为'女'

@Test
public void updateByLambdaUpdateWrapper(){
    LambdaUpdateWrapper<Monster> wrapper = new LambdaUpdateWrapper<>();
    
    wrapper.set(Monster::getGender,'女')
            .like(Monster::getName,"王");
    Monster monster = new Monster();
    
    monsterMapper.update(monster, wrapper);
}

4.3 注意事项和使用细节

(1)mybatis-plus 依赖中包含了 mybatis 和 springboot autoconfigure,无需额外引入

(2)为了开发方便,可以安装MyBatisX插件,参考文档

自动生成sql语句 :

自动生成代码效果如下  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值