七、Java框架之MyBatisPlus

news2024/10/2 12:21:03

黑马课程

文章目录

  • 1. MyBatisPlus入门
    • 1.1 MyBatisPlus入门案例
      • 步骤1:创建spring boot工程
      • 步骤2:配置application.yml
      • 步骤3:创建数据库表(重点)
      • 步骤4:编写dao层
      • 步骤5:测试
    • 1.2 标准数据层开发
      • 标准CRDU使用
      • Lombok
      • 分页功能
      • 配置MP运行日志
  • 2. DQL编程控制 —— 查
    • 2.1 条件查询的三种方式
    • 2.2 多条件查询
    • 2.3 null值处理
    • 2.4 查询投影
    • 2.5 查询条件
      • 环境准备
      • 等值查询
      • 范围查询
      • 模糊匹配
      • 排序查询
    • 2.6 映射匹配兼容性
      • 表名与编码开发设计不同步
      • 表字段与编码属性设计不同步
      • 编码中添加了数据库中未定义的属性
      • 特殊字段不参与查询,如password
  • 3. DML编程控制 —— 增删改
    • 3.1 新增 —— id生成策略
    • 3.2 删除
      • 多记录删除
      • 逻辑删除 @TableLogic
      • 逻辑删除 配置文件方式
    • 3.3 修改 —— 乐观锁
  • 4. 代码生成器
    • 4.1 代码生成器实现
      • 步骤1:导入坐标
      • 步骤2:编写代码生成器
      • 步骤3:测试生成的类

1. MyBatisPlus入门

  • MybatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提供效率

  • 开发方式

    • 基于MyBatis使用MyBatisPlus
    • 基于Spring使用MyBatisPlus
    • 基于SpringBoot使用MyBatisPlus

1.1 MyBatisPlus入门案例

和MyBatis进行比较

步骤1:创建spring boot工程

在选择依赖处,勾选Web/Spring WebSQL/MySQL Driver

  • 注意:这里没有再勾选SQL/MyBatis Framework,这是因为MP并未被收录到idea的系统内置配置,无法直接选择加入,需要手动在pom.xml中配置添加

pom.xml中依赖如下

<dependencies>
    <!-- 自动生成 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- 需手动添加 -->
    <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>
</dependencies>
  • mybatis-plus-boot-starter就导入了mybatis相关坐标,以及spring整合mybatis相关坐标

步骤2:配置application.yml

删除原有的application.properties,新建application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSources

步骤3:创建数据库表(重点)

在之前的项目中,数据库表的表名没有要求
在MyBatisPlus中,数据库表名一定要和domain中的实体类类名相对应!

  • 例如:实体类名为Book,那么数据库表名就应该是book

  • id类型应当为 bigint(20)

    alter table book modify id bigint(20);
    
  • 对应的Book实体类的id也应该是 Long 类型

步骤4:编写dao层

package com.example.dao;

@Mapper
public interface BookDao extends BaseMapper<Book> {
}
  • 只需要继承 BaseMapper<Book>,无需写SQL注解

步骤5:测试

package com.example;

@SpringBootTest
class MybatisplusApplicationTests {
    @Autowired
    private BookDao bookDao;

    @Test
    void testGetAll(){
        List<Book> bookList = bookDao.selectList(null);
        System.out.println(bookList);
    }
}
  • 即便BookDao里面没有写方法,但使用bookDao时,依然会发现许多方法可供使用
  • MP提供了默认的一些简单的增删改查方法,从而无需自己编写

1.2 标准数据层开发

标准CRDU使用

在这里插入图片描述

package com.example.dao;

@Mapper
public interface BookDao extends BaseMapper<Book> {
}
package com.example;

@SpringBootTest
class MybatisplusApplicationTests {
    @Autowired
    private BookDao bookDao;

    @Test
    void testSave(){
        Book book = new Book();
        book.setType("kk");
        book.setName("kk");
        book.setDescription("kk");
        bookDao.insert(book);
    }
    @Test
    void testDelete(){
        bookDao.deleteById(1619646956185972738L);
    }
    @Test
    void testUpdate(){
        Book book = new Book();
        book.setId(1L);
        book.setType("kk2");
        bookDao.updateById(book);
    }
    @Test
    void testGetById(){
        Book book = bookDao.selectById(1L);
        System.out.println(book);
    }
    @Test
    void testGetAll(){
        List<Book> bookList = bookDao.selectList(null);
        System.out.println(bookList);
    }

}

Lombok

一个Java类库,提供了一组注解,简化POJO实体类开发

步骤1:导入jar包

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

报错的话,加上版本号;否则不加

步骤2:在实体类上加上注解

在之前都是需要手动添加getter, setter, toString等方法,现在可以用以下注解替代

package com.example.domain;

@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode//自动生成hashCode
public class Book {
    private Long id;
    private String name;
    private String type;
    private String description;
}

更进一步,可以简化成

package com.example.domain;

@Data
public class Book {
    private Long id;
    private String name;
    private String type;
    private String description;
}
  • @Data包含除构造器外的其他方法

分页功能

步骤1:编写拦截器

拦截器MP已经提供,只需要将其配置成Spring管理的bean对象即可

package com.example.config;

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

步骤2:分页查询

分页查询使用的方法是:

IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper)
  • IPage:用来构建分页查询条件,第几页,一页多少行
  • Wrapper:用来构建条件查询的条件,目前我们没有可直接传为Null
  • IPage:返回值,构建分页条件和方法的返回值都是IPage
@Test
void testGetByPage(){
    IPage page = new Page(1, 5);//查询第1页,每页10行
    bookDao.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运行日志

application.yml中增加

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

此时有很多日志输出,但许多暂时用不到,需要将其删除,此时可以新建一个 logback.xml,如下

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

一些日志已经不再显示,现在取消MybatisPlus启动banner图标,在application.yml中增加内容如下

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

还剩下springboot的banner,如果需要将其删除,在 application.yml 中配置如下

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimeZone=UTC
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource
  main:
    banner-mode: off

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

2. DQL编程控制 —— 查

bookDao.selectList(null) 查看selectList源码,发现它需要一个Wrapper<T>的参数
查看wrapper<T>,发现其为一个抽象类

public abstract class Wrapper<T> implements ISqlSegment {...}

ctrl+h 查看其继承类

在这里插入图片描述

其中 QueryWrapper 即是需要的实现类

2.1 条件查询的三种方式

//查询 id<6 的数据
@Test
void testGetAll(){
    //方式一:按条件查询
    QueryWrapper qw = new QueryWrapper();
    qw.lt("id", 6);

    //方式二:lambda格式按条件查询
    QueryWrapper<Book> qw = new QueryWrapper<Book>();
    qw.lambda().lt(Book::getId, 6);

    //方式三(推荐):lambda格式按条件查询
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    lqw.lt(Book::getId, 6);

    List<Book> bookList = bookDao.selectList(lqw);
    System.out.println(bookList);
}

2.2 多条件查询

  • and 查询

    //查询 id>6 但 <10的数据
    lqw.gt(Book::getId, 6).lt(Book::getId, 10);
    

    或者

    lqw.gt(Book::getId, 6);
    lqw.lt(Book::getId, 10);
    
  • or 查询

    //查询 id<3 或者 id>10的数据
    lqw.lt(Book::getId, 3).or().gt(Book::getId, 10);
    

2.3 null值处理

//模拟页面传递过来的查询数据:查询 5<id<10的数据
Long idMin = null;
Long idMax = 10L;

LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
//null判断:先判定是否为null,如果为null,就不连接
lqw.lt(null != idMax, Book::getId, idMax);
lqw.gt(null != idMin, Book::getId, idMin);

List<Book> bookList = bookDao.selectList(lqw);
System.out.println(bookList);

2.4 查询投影

  • 查询指定字段

    //查询投影:只适应lambda的格式
    LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
    lqw.select(Book::getId, Book::getName, Book::getType);
    List<Book> bookList = bookDao.selectList(lqw);
    
    //查询投影:非lambda的格式
    QueryWrapper<Book> qw = new QueryWrapper<Book>();
    qw.select("id", "name", "type");
    List<Book> bookList = bookDao.selectList(qw);
    
  • 聚合查询

    完成count、max、min、avg、sum的使用

    @Test
    void testGetAll(){
        QueryWrapper<Book> qw = new QueryWrapper<Book>();
        //1. 计算总记录数
        qw.select("count(*) as count, type");
        //2. 按type分组
        qw.groupBy("type");
        //3. 获取数据
        List<Map<String, Object>> bookList = bookDao.selectMaps(qw);
        System.out.println(bookList);
    }
    

    在这里插入图片描述

当MyBatisPlus无法处理需要的SQL要求时,仍然可以在bookDao中按老方法进行编写

2.5 查询条件

其他条件查询使用方法可以去官网的指南上查询:https://baomidou.com/

环境准备

准备:user数据库表,User类等

数据库表

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,'玛丽','123456',15,'4006184000');

User实体类

package com.example.domain;

@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private int age;
    private String tel;
}

UserDao

package com.example.dao;

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

等值查询

需求:根据用户名和密码查询用户信息

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.eq(User::getName, "玛丽").eq(User::getPassword, "123456");//实际中密码需要md5加密
User user = userDao.selectOne(lqw);

范围查询

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.between(User::getAge, 10, 50);
List<User> userList = userDao.selectList(lqw);

模糊匹配

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.like(User::getName, "J");//匹配 %J%
lqw.likeLeft(User::getName, "J");//匹配 %J
lqw.likeRight(User::getName, "J");//匹配 J%
List<User> userList = userDao.selectList(lqw);
  • like():前后加百分号,如 %J%
  • likeLeft():前面加百分号,如 %J
  • likeRight():后面加百分号,如 J%

排序查询

需求:查询所有数据,然后按照id降序

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
/**
 * condition :条件,返回boolean,当condition为true,进行排序,如果为false,则不排序
 * isAsc:是否为升序,true为升序,false为降序
 * columns:需要操作的列
 * 下面表示,进行排序,升序,排序字段是age
 */
lqw.orderBy(true, true, User::getAge);
List<User> userList = userDao.selectList(lqw);

2.6 映射匹配兼容性

表名与编码开发设计不同步

  • 准备:将数据库表user修改为 tbl_user,以进行演示

    alter table user rename to tbl_user;
    

    此时数据库表名为tbl_user,实体类为User,MP将不能正确识别

  • 只需要在User实体类上添加@TableName注解即可

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    private String password;
    private int age;
    private String tel;
}

如果希望对所有实体类都进行这样的替换,可以用全局配置替换@TableName

#替换所有实体类对应的表名
mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_user

表字段与编码属性设计不同步

  • 准备:将数据库表tbl_user中的字段password改为pwd

    alter table user change password pwd varchar(32) not null;
    
  • 只需要在User实体类对应字段加上@TableField注解即可

此时数据库表名为tbl_user,实体类为User,MP将不能正确识别

@Data
public class User {
    private Long id;
    private String name;
    @TableField(value = "pwd")
    private String password;
    private int age;
    private String tel;
}

编码中添加了数据库中未定义的属性

例如:在插入数据时,User实体类中有一个online属性,但数据库表user中没有这个字段,此时将报错,解决方法如下

@TableField(exist = false)

@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private int age;
    private String tel;
    @TableField(exist = false)
    private Integer online;
}

特殊字段不参与查询,如password

password将不参与查询,需要隐藏起来

@Data
public class User {
    private Long id;
    private String name;
    @TableField(value = "pwd", select = false)
    private String password;
    private int age;
    private String tel;
}

这样设置后,查询后password字段将为空

3. DML编程控制 —— 增删改

3.1 新增 —— id生成策略

@Data
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
}

如果希望设置所有实体类的id生成策略,需要在application.yml文件中配置

#设置id生成策略
mybatis-plus:
  global-config:
    db-config:
      id-type: assign_id

IdType有以下几种

  • Auto:数据库id自增
  • NONE:不设置id生成策略
  • INPUT:用户手工输入id
  • ASSIGN_ID(默认):雪花算法生成id(可兼容数值型与字符串型)
  • ASSIGN_UUID:以UUID生成算法作为id生成策略
  • 其他的几个策略 ID_WORKER, ID_WORKER_STR, UUID 均已过时,都将被ASSIGN_ID和ASSIGN_UUID代替掉。

雪花算法

生成一个64位的二进制数字,及Long的大小

在这里插入图片描述

  • 1bit,不用,因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0

  • 41bit-时间戳,用来记录时间戳,毫秒级

  • 10bit-工作机器id,用来记录工作机器id,其中高位5bit是数据中心ID,其取值范围0-31
    低位5bit是工作节点ID,其取值范围0-31,两个组合起来最多可以容纳1024个节点

  • 序列号占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID

3.2 删除

多记录删除

deleteBatchIds

List<Long> list = new ArrayList<>();
list.add(1619725419349172225L);
list.add(6L);
list.add(5L);
userDao.deleteBatchIds(list);

同理,也可以多数据查询:selectBatchIds

逻辑删除 @TableLogic

场景
人员表:删除了人员zhangsan
订单表:zhangsan对应的订单order1,order2成为脏数据,或者跟着一起被删除,因此无法被读取
结果:之后年度汇总,发现订单数量对不上
解决方案:逻辑标记

逻辑删除

为数据设置是否可用状态字段 deleted,删除时设置状态字段为不可用状态,数据保留在数据库中,执行的是update操作

  • 使用 @TableLogic注解 标注 删除标识字段
  • 设置了标识字段也不会影响 select 语句,因此此后在查询时会自动添加如 where selected=0
  • 如果设置了标识字段,又想看到已被删除的数据,那么需要自己写sql语句

步骤1:为数据库表增加逻辑删除字段 deleted,设置默认值为0,未删除

alter table user add deleted int default 0;

步骤2:在实体类User中增加删除标识字段deleted

@Data
public class User {
    private Long id;
    private String name;
    @TableField(select = false)
    private String password;
    private int age;
    private String tel;
    //增加删除字段:value表示未删除,delval表示已删除
    @TableLogic(value = "0", delval = "1")
    private Integer deleted;
}

步骤3:运行删除方法

userDao.deleteById(1L);

发现执行的是update语句,且数据库该条数据仍存在

在这里插入图片描述

逻辑删除 配置文件方式

在 User实体类 中添加删除字段

private Integer deleted;

在 application.yml 中配置

#配置删除字段
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-not-delete-value: 0
      logic-delete-value: 1

3.3 修改 —— 乐观锁

这里的方案适用于小系统,并发在2000以下

  • 悲观锁:每次使用共享资源前先上锁
  • 乐观锁:通常是在表里加一个版本或时间戳,要更新前检查一下自己保存的版本和表现在的版本对比,如果不一样,说明被更改过了,于是通知操作者重新操作

步骤1:在数据库中增加列version,标记当前版本号

alter table user add version int default 1;

步骤2:在实体类中添加字段 version,并添加注解@Version

package com.example.domain;

@Data
public class User {
    private Long id;
    private String name;
    @TableField(select = false)
    private String password;
    private int age;
    private String tel;
    //增加删除字段:value表示未删除,delval表示已删除
    @TableLogic(value = "0", delval = "1")
    private Integer deleted;
    //增加版本字段
    @Version
    private Integer version;
}

步骤3:添加乐观锁的拦截器

package com.example.config;

@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mpInterceptor(){
        //1. 定义MP拦截器
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2. 添加之前的分页拦截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //3. 添加乐观锁拦截器
        //作用:修改时,将在SQL语句中添加 set version=version+1
        mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mpInterceptor;
    }
}

步骤4:测试

//1. 通过要修改的数据id将当前的数据查询处理
User user = userDao.selectById(2L);
//2. 修改属性值
user.setName("Lili");
//3. 进行修改
userDao.updateById(user);

在执行前,表中该条数据的version是1,执行后version为2

  • 一定要获取数据,这样来获取到当前的版本号
  • 修改时,会将自己目前的版本号和数据库版本号比对,来判断在该条数据是否被修改过

步骤5:模拟并发情况

@Test
void testUpdate(){
    //1. user1和user2同时访问第1条数据
    User user1 = userDao.selectById(4L); //version = 1;
    User user2 = userDao.selectById(4L); //version = 1;

    //2. user2对第1条数据进行了修改
    user2.setName("user2");
    userDao.updateById(user2); //version = 2;

    //3. user1此时再对第1条数据进行修改:失败
    user1.setName("user1");
    userDao.updateById(user1);
}

user1更新失败,因为它的version=1,而数据库该条数据已经变为 version=2
此时,user1需要重新操作:再获取一次数据,然后再更新

4. 代码生成器

像是BookDao,UserDao,这些类都有相似的结构,可以抽取出来做成模板,这也就是代码生成器的原理

  • 模板:MyBatisPlus提供,可以自己提供,但是麻烦,不建议
  • 数据库相关配置:读取数据库获取表和字段信息
  • 开发者自定义配置:手工配置,比如ID生成策略

4.1 代码生成器实现

步骤1:导入坐标

<dependencies>
    <!-- spring webmvc -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- mysql -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- mybatisplus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.1</version>
    </dependency>
    <!-- druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
    <!-- 代码生成器 -->
    <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>
</dependencies>

步骤2:编写代码生成器

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 CodeGenerator {
    public static void main(String[] args){
        //1. 定义一个自动生成器对象
        AutoGenerator autoGenerator = new AutoGenerator();

        //2. 设置数据源
        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/ssm_db?useSSL=false&serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        autoGenerator.setDataSource(dataSource);

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

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

        //5. 策略配置(核心)
        StrategyConfig strategyConfig = new StrategyConfig();
//        strategyConfig.setInclude("tbl_table1", "tbl_table2");//生成指定的表(必须要存在)
        strategyConfig.setTablePrefix("tbl_");//去掉前缀,如:数据库表名为tbl_book,那么生成的dao就为BookDao,否则为Tbl_bookDao
        strategyConfig.setRestControllerStyle(true);//设置是否启用RESTful风格
        strategyConfig.setEntityLombokModel(true);//设置是否启用Lombok
        strategyConfig.setLogicDeleteFieldName("deleted");//设置逻辑删除字段名
        strategyConfig.setVersionFieldName("version");//设置乐观锁字段
        autoGenerator.setStrategy(strategyConfig);

        //6. 执行生成操作
        autoGenerator.execute();
    }
}
  • dao层生成的类还需要添加上 @Mapper 注解

步骤3:测试生成的类

在这里插入图片描述

注意:在使用代码生成器时,application.yml中的内容可以为空
但是如果要在测试中使用方法,需要在application.yml中补齐dataSource的配置

代码生成器生成的结果如上,在Test类中测试

@SpringBootTest
class MybatisplusApplicationTests {
    @Autowired
    private IUserService userService;

    @Test
    void contextLoads(){
        User user = userService.getById(2L);
        System.out.println(user);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337910.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSDN每日一练:一维数组的最大子数组和

题目名称&#xff1a;一维数组的最大子数组和 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述 下面是一个一维数组的 “最大子数组的和” 的动态规划的解法 # include <iostream> # include <stdio.h> # include <string.h>int MaxSum(int* a…

多传感器融合定位十五-多传感器时空标定(综述)

多传感器融合定位十五-多传感器时空标定1. 多传感器标定简介1.1 标定内容及方法1.2 讲解思路2. 内参标定2.1 雷达内参标定2.2 IMU内参标定2.3 编码器内参标定2.4 相机内参标定3. 外参标定3.1 雷达和相机外参标定3.2 多雷达外参标定3.3 手眼标定3.4 融合中标定3.5 总结4. 时间标…

基于live555源码的rtsp服务器

下载live555源码 http://www.live555.com/liveMedia/public/ 在Linux系统的自定义目录下输入&#xff0c;下载源码&#xff1a; wget http://www.live555.com/liveMedia/public/live.2023.01.19.tar.gz解压源码&#xff1a; tar -xvf live.2023.01.19.tar.gz当前目录下运行&…

前端卷算法系列(一)

前端卷算法系列&#xff08;一&#xff09; 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同…

无重复字符的最长子串-力扣3-java

一、题目描述给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入: s "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2:输入: s "bbbbb"输出: 1解释: 因为…

Springboot Web开发

文章目录一. 静态资源访问1. 配置静态资源访问前缀2. 修改默认静态资源存放目录3. Webjars4. 欢迎页支持5. 自定义Favicon二. 请求处理1. 路径变量2. 请求头处理3. 查询字符串处理4. 获取Cookie的值5. 获取请求体的值6. 获取请求域中的数据7. 矩阵变量一. 静态资源访问 只要静…

ChatGPT全球爆火,究竟有何特别之处?

​ 新年复工不过半月&#xff0c;职场人似乎就受到了来自AI的“威胁”&#xff0c;关于人工智能聊天系统ChatGPT的热搜频频上榜。 ChatGPT不仅拟人&#xff0c;更类人&#xff0c;甚至被认为是职场人的“敌人”。 那么&#xff0c;ChatGPT能替代哪些职业&#xff1f; 它自己的回…

STP协议基础

STP协议技术来源二层环路及危害二层交换机网络的冗余性与环路人为错误导致的二层环路二层环路带来的问题STP生成树协议STP概述STP基本概念桥ID根桥COSTRPC&#xff08;Root Path Cost&#xff09;根路径开销PORT ID端口IDBPDU桥协议数据单元STP的计算过程&#xff08;1&#xf…

VS中安装gismo库

文章目录前言一、下载安装paraview直接下载压缩包安装就可以了解压后按步骤安装即可二、gismo库的安装gismo库网址第一种方法&#xff1a;第二种方法第三种方法&#xff1a;用Cmake软件直接安装首先下载cmake软件[网址](https://cmake.org/download/)安装gismo库三、gismo库的使…

ChatGPT闭包解答

怎么理解javaScript闭包 JavaScript 闭包是一种特殊的对象&#xff0c;它包含了函数及其相关作用域中的变量。它允许函数访问并保存其外部作用域中的变量&#xff0c;即使该函数已经离开了其作用域。 闭包的一个常见应用场景是封装私有变量。例如&#xff0c;在一个对象的方法内…

Android IO 框架 Okio 的实现原理,如何检测超时?

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 前言 大家好&#xff0c;我是小彭。 在上一篇文章里&#xff0c;我们聊到了 Square 开源的 I/O 框架 Okio 的三个优势&#xff1a;精简且全面的 API、基于共享的缓冲区设计以…

电机参数中力矩单位kgf.cm,Nm,mNm表示的含义

力的基本知识 质量和力的比例系数 质量和重力的关系有一个重力系数&#xff1a;g≈9.8 N/kg≈10,后面看到的1kgf就相当于1kg物体的力也就是10N 杠杆原理 对于同一个支点&#xff0c;在不考虑杠杆的重量的情况下&#xff0c;实现同样的作用效果&#xff0c;距离支点越近&…

vscode搭建python Django网站开发环境

这里使用pip安装的方式&#xff0c;打开命令行&#xff0c;输入执行&#xff1a; pip install django2.2这里选择安装2.2版本是因为是新的lts版本&#xff0c;长期支持稳定版。 接下来再安装pillow&#xff0c;Django底层一部分是基于pillow进行的。 pip install pillowpylint…

SpringBoot + Disruptor实现高并发内存消息队列

1. 简介 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列&#xff0c;研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCon演讲后&#xff0c;获得了业界关…

【思维模型】概率思维的价值:找到你的人生算法,实现阶级跃迁!

把同样公平的机会放在放在很多人面前,不同的人生算法,会得到迥然不同的结果。 概率思维是什么? 【ChatGPT】概率思维是一种通过使用数学模型来思考和评估不确定性事件的方法。它通过计算不同可能性的概率来预测事件的结果,并评估风险和机会。 概率思维的价值在于它可以帮…

ChatYuan元语AI: 类似ChatGPT功能型对话大模型

ChatYuan元语AI 元语智能开发团队训练了一个类似ChatGPT的功能型对话大模型ChatYuan. 类似ChatGPT模型, 中文开源版,功能型对话大语言模型. 功能有:支持训练端到端文本生成文本生成情感分析句子相似度零样本分类命名实体识别翻译自然语言推理问答文本纠错文本摘要FAQ问答文本…

终于体验了一下ChatGPT

再次尝试 隔了一天&#xff0c;今天&#xff08;2023-2-11&#xff09;再试一下。真的是一下。。。&#xff08;如果没有境外环境的&#xff0c;大家还是在网上找个共享账号试一下吧。网上有人分享的&#xff0c;大家细找一下就可以&#xff0c;我就不在这里发出来了。。。&…

微信小程序 Springboot校运会高校运动会管理系统

3.1小程序端 小程序登录页面&#xff0c;用户也可以在此页面进行注册并且登录等。 登录成功后可以在我的个人中心查看自己的个人信息或者修改信息等 在广播信息中我们可以查看校运会发布的一些信息情况。 在首页我们可以看到校运会具体有什么项目运动。 在查看具体有什么活动我…

“笨办法”学Python 3 ——练习 37. 复习各种符号

练习 37. 复习各种符号 关键词 可参考&#xff1a;https://www.knowledgedict.com/tutorial/python-keyword.html 数据类型 可参考&#xff1a;https://www.knowledgedict.com/tutorial/python-data-type.html 如果需要查看变量的类型。可以使用Python的内置类type。 例如…

【Python小游戏】通过这款专为程序员设计的《极限车神》小游戏,你的打字速度可以赢过专业录入员,这个秘密98%的人都不知道哦~(爆赞)

导语 哈喽&#xff0c;我是你们的木木子&#x1f478;&#xff01; 今天小编要为大家介绍一款小编自己用代码码出来的赛车风格的打字小游戏 取名暂定为《&#x1f697;极限车神&#x1f697;》打字小游戏。 这款Pygame小游戏在玩法上可以说十分创新&#xff0c;不仅能游戏还…