7.SSM-MyBatisPlus

1.MyBatisPlus简介

1.1 入门案例

建表sql

CREATE DATABASE mybatisplus_db;
USE mybatisplus_db;

CREATE DATABASE IF NOT EXISTS mybatisplus_db CHARACTER SET utf8;
USE mybatisplus_db;
CREATE TABLE USER (
id BIGINT(20) PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL,
PASSWORD VARCHAR(32) NOT NULL,
age INT(3) NOT NULL ,
tel VARCHAR(32) NOT NULL
);
INSERT INTO USER VALUES(1,'Tom','tom',3,'18866668888');
INSERT INTO USER VALUES(2,'Jerry','jerry',4,'16688886666');
INSERT INTO USER VALUES(3,'Jock','123456',41,'18812345678');
INSERT INTO USER VALUES(4,'传智播客','itcast',15,'4006184000');

实验步骤
① 创建SpringBoot项目,勾选MySQL Driver
② 添加依赖坐标

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>

注意事项:由于mp未被收录到idea的系统内置配置,无法直接选择加入

③ 配置数据库参数

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://192.168.1.224:3306/mybatisplus_db
    username: root
    password: 123456

④ 创建domain.User对象

package com.example.domain;

public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", tel='" + tel + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }
}

⑤ 定义数据接口,继承BaseMapper

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.domain.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserDao extends BaseMapper<User> {
}

⑥ 测试类中注入dao接口,测试功能

package com.example;

import com.example.dao.UserDao;
import com.example.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringbootMybatisplusApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {
        List<User> userList = userDao.selectList(null);
        System.out.println(userList);
    }

}

1.2 MyBatisPlus概述

MyBatisPlus是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率
官网:https://baomidou.com/

MyBatisPlus特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.标准数据层开发

标准数据层CRUD功能

功能自定义接口MP接口
新增boolean save(T t)int insert(T t)
删除boolean delete(int id)int deleteById(Serializable id)
修改boolean update(T t)int updateById(T t)
根据id查询T getById(int id)T selectById(Serializable id)
查询全部List getAll()List selectList()
分页查询pageInfo getAll(int page,int size)IPage selectPage(IPage page)
按条件查询List getAll(Condition condition)IPage selectPage(Wrapper queryWrapper)

测试MP接口

package com.example;

import com.example.dao.UserDao;
import com.example.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class SpringbootMybatisplusApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testSave(){
        User user = new User();
        user.setAge(11);
        user.setName("小王");
        user.setPassword("xiaowang");
        user.setTel("123456");
        userDao.insert(user);
    }

    @Test
    void testDelete(){
        userDao.deleteById(1530454523057905666L);
    }

    @Test
    void testGetById(){
        User user = userDao.selectById(1L);
        System.out.println(user);
    }

    @Test
    void testUpdate(){
        User user = new User();
        user.setId(1L);
        user.setName("Tom666");
        userDao.updateById(user);
    }

    @Test
    void testGetAll() {
        List<User> userList = userDao.selectList(null);
        System.out.println(userList);
    }

}

lombok
导入依赖坐标

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

使用lombok注解创建实体类

package com.example.domain;

import lombok.*;

//@Setter
//@Getter
//@ToString
//@NoArgsConstructor
//@AllArgsConstructor
//@EqualsAndHashCode
@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}

@Data可以代替get/set方法,有参/无参构造器方法,toString方法,hashCoded方法,equals方法等

2.1 分页功能

① 设置分页拦截器作为Spring管理的bean

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //1.定义Mp拦截器
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2.在Mp拦截器中添加具体的拦截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mpInterceptor;
    }
}

② 测试分页功能

    @Test
    void testGetByPage(){
        IPage page = new Page(1,2);
        userDao.selectPage(page,null);
        System.out.println("当前页码值:" + page.getCurrent());
        System.out.println("每页显示数:" + page.getSize());
        System.out.println("一共多少页:" + page.getPages());
        System.out.println("一共多少条数据:" + page.getTotal());
        System.out.println("数据:" + page.getRecords());
    }

开启日志

# 开启mp的日志(输出到控制台的日志)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.DQL编程控制

3.1 条件查询

MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合

关闭系统日志显示
resources包下创建logback.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>

修改配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://192.168.1.224:3306/mybatisplus_db
    username: root
    password: 123456
  main:
    banner-mode: off

# 开启mp的日志(输出到控制台的日志)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false

条件查询示例

    @Test
    void testGetAll(){
       //方式一:按条件查询
//        QueryWrapper qw = new QueryWrapper();
//        qw.lt("age",18);
//        List<User> userList = userDao.selectList(qw);
//        System.out.println(userList);

        //方式二:lambda格式按条件查询
//        QueryWrapper<User> qw = new QueryWrapper<>();
//        qw.lambda().lt(User::getAge,18);
//        List<User> userList = userDao.selectList(qw);
//        System.out.println(userList);

        //方式三:lambda格式按条件查询
//        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//        lqw.lt(User::getAge,18);
//        List<User> userList = userDao.selectList(lqw);
//        System.out.println(userList);

        //多条件
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //18到50之间
//        lqw.lt(User::getAge,50);
//        lqw.gt(User::getAge,18);
        //链式编程
//        lqw.lt(User::getAge,50).gt(User::getAge,18);
        //小于10岁或者大于18岁
        lqw.lt(User::getAge,10).or().gt(User::getAge,18);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
3.1.1 null值处理

用于限定age的上限

package com.example.domain.query;

import com.example.domain.User;
import lombok.Data;

@Data
public class UserQuery extends User {
    private Integer age2;
}

测试

    @Test
    void testGetAll2() {
        //模拟页面传递过来的查询数据
        UserQuery uq = new UserQuery();
        uq.setAge(10);
//        uq.setAge2(30);
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //先判定第一个条件是否为true,如果为true连接当前条件
        lqw.lt(null != uq.getAge2(),User::getAge,uq.getAge2())
                .gt(null != uq.getAge(),User::getAge,uq.getAge());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }

3.2 查询投影

    @Test
    void testGetAll3() {
        //查询投影
//        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//        lqw.select(User::getId,User::getName,User::getAge);
////        QueryWrapper<User> lqw = new QueryWrapper<>();
////        lqw.select("id","name","age");
//        List<User> userList = userDao.selectList(lqw);
//        System.out.println(userList);

        QueryWrapper<User> lqw = new QueryWrapper<>();
        lqw.select("count(*) as count,tel")
                .groupBy("tel");
        List<Map<String,Object>> userList = userDao.selectMaps(lqw);
        System.out.println(userList);
    }

3.3 查询条件

https://baomidou.com/pages/10c804/
查询条件在 核心功能 的 条件构造器 中查找

    @Test
    void testGetAll4() {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        //等同于=
//        lqw.eq(User::getName,"Jerry")
//                .eq(User::getPassword,"jerry");
//        User user = userDao.selectOne(lqw);
//        System.out.println(user);

        //范围发查询lt le gt ge between
//        lqw.between(User::getAge,10,30);
//        List<User> userList = userDao.selectList(lqw);
//        System.out.println(userList);

        //模糊匹配
        lqw.like(User::getName,"J");
//        lqw.likeRight(User::getName,"J");
//        lqw.likeLeft(User::getName,"J");
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }

3.4 字段映射与表名映射

1.问题一:表字段与编码属性设计不同步
@TableField:设置当前属性对应的数据库表中的字段关系

public class User {
    @TableField(value = "pwd")
    private String password;
}

2.问题二:编码中添加了数据库中未定义的属性

public class User {
    @TableField(exist = "false")
    private Integer online;
}

3.问题三:采用默认查询开放了更多的字段查询权限

public class User {
    @TableField(value = "pwd",select = false)
    private String password;
}

4.问题四:表名与编码开发设计不同步
@TableName:设置当前类对应于数据库表关系

@TableName("tbl_user")
public class User {
    @TableField(value = "pwd",select = false)
    private String password;
}

4.DML编程控制

4.1 id生成策略控制

不同的表应用不同的id生成策略
1.日志:自增(1,2,3,4,……)
2.购物订单:特殊规则(FQ23948AK3843)
3.外卖单:关联地区日期等信息(10 04 20200314 34 91)
4.关系表:可省略id

@TableId:设置当前类中主键属性的生成策略

public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
}
  • AUTO(0):使用数据库id自增策略控制id生成
  • NONE(1): 不设置id生成策略
  • INPUT(2):用户手工输入id
  • ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)
  • ASSIGN_UUID(4):以UUID生成算法作为id生成策略

全局配置

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false
    db-config:
      #id自增策略
      id-type: assign_id
      #表名前缀
      table-prefix: tbl_

4.2 多数据操作(删除)

添加和多数据删除

    @Test
    void testInsert(){
        User user = new User();
        user.setAge(11);
        user.setName("小王");
        user.setPassword("xiaowang");
        user.setTel("123456");
        User user1 = new User();
        user1.setAge(12);
        user1.setName("小华");
        user1.setPassword("xiaohua");
        user1.setTel("1234568");
        userDao.insert(user);
        userDao.insert(user1);
    }

    @Test
    void testDelete(){
        List<Long> list = new ArrayList<>();
        list.add(1530525838229913601L);
        list.add(1530525929594437633L);
        userDao.deleteBatchIds(list);

//        List<Long> list = new ArrayList<>();
//        list.add(1L);
//        list.add(2L);
//        userDao.selectBatchIds(list);
    }

逻辑删除
删除业务问题:业务数据从数据库中丢弃
逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中。

mysql的user表添加一个delete字段(int,长度为1,默认值为0)

User中添加逻辑删除字段的属性

package com.example.domain;

import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.*;

@Data
public class User {
//    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
    //逻辑删除字段,标记当前是否被删除
    @TableLogic(value = "0",delval = "1")
    private Integer deleted;
}

进行逻辑删除

    @Test
    void testDelete(){
        userDao.deleteById(1L);
    }

全局配置代替注解

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0

4.3 乐观锁

① 给user添加字段version(int,长度11,默认值1)
② 在实体类中添加属性和注解

package com.example.domain;

import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.*;

@Data
public class User {
//    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
    //逻辑删除字段,标记当前是否被删除
//    @TableLogic(value = "0",delval = "1")
    private Integer deleted;
    @Version
    private Integer version;
}

③ 添加乐观锁的拦截器

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //1.定义Mp拦截器
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2.在Mp拦截器中添加具体的拦截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //3.添加乐观锁的拦截器
        mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mpInterceptor;
    }
}

④ 测试

    @Test
    void testUpdate(){
//        User user = new User();
//        user.setId(3L);
//        user.setName("Jock666");
//        user.setVersion(1);
//        userDao.updateById(user);

        //1.先通过要修改的数据id将当前数据查询出来
        User user = userDao.selectById(3L); //version=3
        User user2 = userDao.selectById(3L);//version=3

        //2.将要修改的属性逐一设置进去
        user2.setName("Jock999");
        userDao.updateById(user2);//version=4

        user.setName("Jock888");
        userDao.updateById(user);//version不等于3,失效
    }

5.代码生成器

模板:MyBatisPlus提供
数据库相关配置:读取数据库获取信息
开发者自定义配置:手工配置

① 添加依赖坐标

<!--代码生成器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>
<!--velocity模板引擎-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

② 代码生成器

package com.example;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;

public class Generator {
    public static void main(String[] args) {
        //1.获取代码生成器的对象
        AutoGenerator autoGenerator = new AutoGenerator();

        //设置数据库相关配置
        DataSourceConfig datasource = new DataSourceConfig();
        datasource.setDriverName("com.mysql.cj.jdbc.Driver");
        datasource.setUrl("jdbc:mysql://192.168.1.224:3306/mybatisplus_db");
        datasource.setUsername("root");
        datasource.setPassword("123456");
        autoGenerator.setDataSource(datasource);

        //设置全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");    //设置代码生成位置
        globalConfig.setOpen(false);    //设置生成完毕后是否打开生成代码所在的目录
        globalConfig.setAuthor("www");    //设置作者
        globalConfig.setFileOverride(true);     //设置是否覆盖原始生成的文件
        globalConfig.setMapperName("%sDao");    //设置数据层接口名,%s为占位符,指代模块名称
        globalConfig.setIdType(IdType.ASSIGN_ID);   //设置Id生成策略
        autoGenerator.setGlobalConfig(globalConfig);

        //设置包名相关配置
        PackageConfig packageInfo = new PackageConfig();
        packageInfo.setParent("com.test");   //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        packageInfo.setEntity("domain");    //设置实体类包名
        packageInfo.setMapper("dao");   //设置数据层包名
        autoGenerator.setPackageInfo(packageInfo);

        //策略设置
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("user");  //设置当前参与生成的表名,参数为可变参数
        strategyConfig.setTablePrefix("");  //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名  例如: User = tbl_user - tbl_
        strategyConfig.setRestControllerStyle(true);    //设置是否启用Rest风格
        strategyConfig.setVersionFieldName("version");  //设置乐观锁字段名
        strategyConfig.setLogicDeleteFieldName("deleted");  //设置逻辑删除字段名
        strategyConfig.setEntityLombokModel(true);  //设置是否启用lombok
        autoGenerator.setStrategy(strategyConfig);

        //2.执行生成操作
        autoGenerator.execute();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值