mybatisPlus

3/20/2023

# MyBatis-Plus

image-20221204220000764

# 配置:

# pom.xml

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>
1
2
3
4
5

# application.yaml

#配置端口
server:
  port: 8888

spring:
  #配置数据源
  datasource:
    #配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
    #配置连接数据库的信息
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xxx?characterEncoding=utf-8&useSSL=false
    username: root
    password: 

#MyBatis-Plus相关配置
mybatis-plus:
  configuration:
    #配置日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 启动类加@MapperScan("xxx")

@SpringBootApplication
@MapperScan("指定Mapper接口所在的包")
public class MybatisPlusDemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(MybatisPlusDemoApplication.class, args);
	}
}
1
2
3
4
5
6
7

# 开干:

# 编写实体类

# 编写service接口

public interface UserService extends IService<User> {

}
1
2
3

# 编写service实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
	
}
1
2
3
4

# 编写Mapper接口

public interface UserMapper extends BaseMapper<User> {
    
}
1
2
3

# 常用注解:

# @TableName

  • 默认操作的表名和实体类型的类名一致

  • 不一致时在实体类上加@TableName("表名")

  • 使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就不需要在每个实体类上通过@TableName标识实体类对应的表

    mybatis-plus:
      global-config:
        db-config:
          # 设置实体类所对应的表的统一前缀
          table-prefix: t_
    
    1
    2
    3
    4
    5

# @TableId

  • 默认实体类和表中表示主键是id

  • 不是id时(如uid),在实体类中uid属性上通过@TableId将其标识为主键

  • value属性:

    • 指定表中的主键字段,@TableId("uid")@TableId(value="uid")
    • 使用场景:若实体类中主键对应的属性为id,而表中表示主键的字段为uid,此时若只在属性id上添加注解@TableId,则抛出异常Unknown column 'id' in 'field list'
  • type属性:

    • 用来定义主键策略:默认雪花算法

    • 描述
      IdType.ASSIGN_ID(默认) 基于雪花算法的策略生成数据id,与数据库id是否设置自增无关
      IdType.AUTO 使用数据库的自增策略,注意,该类型请确保数据库设置了id自增,
    • ​ 配置全局主键策略:

      mybatis-plus:
        global-config:
          db-config:
      		#配置mp的主键策略为自增
            	id-type: auto
      
      1
      2
      3
      4
      5

# @TbaleField

  • MyBatis-Plus在执行SQL语句时,要保证实体类中的属性名和表中的字段名一致

  • 不一致时:

    • 驼峰:MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格

    • 非驼峰(如实体类属性name,表中字段username):在实体类属性上使用@TableField("username")设置属性所对应的字段名

      public class User {
          @TableId("uid")
          private Long id;
          @TableField("username")
          private String name;
          private Integer age;
          private String email;
      }
      
      1
      2
      3
      4
      5
      6
      7
      8

# @TableLogic

  • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

  • 实现:

    • 在数据库中创建逻辑删除状态列(is_deleted),设置默认值为0

    • 实体类中添加逻辑删除属性

      @TableLogic
      private int isDeleted;
      
      1
      2

# 条件构造器:

image-20221204222610932

  • Wrapper : 条件构造抽象类,最顶端父类
    • AbstractWrapper: 用于查询条件封装,生成 sql 的 where 条件
      • QueryWrapper: 查询条件封装

      • UpdateWrapper: Update 条件封装

      • AbstractLambdaWrapper: 使用Lambda 语法

        • LambdaQueryWrapper:用于Lambda语法使用的查询Wrapper

        • LambdaUpdateWrapper: Lambda 更新封装Wrapper

# QueryWrapper

  • 组装查询条件

    **执行SQL:**SELECT uid AS id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (username LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)

    public void test01(){
        //查询用户名包含a,年龄在20到30之间,邮箱信息不为null的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("username","a").between("age",20,30).isNotNull("email");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 组装排序条件

    **执行SQL:**SELECT uid AS id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 ORDER BY age DESC,id ASC

    public void test02(){
        //查询用户信息,按照年龄的降序排序,若年龄相同,则按照id升序排序
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("age").orderByAsc("id");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 组装删除条件

    **执行SQL:**UPDATE t_user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)

    public void test03(){
        //删除邮箱地址为null的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("email");
        int result = userMapper.delete(queryWrapper);
        System.out.println(result > 0 ? "删除成功!" : "删除失败!");
        System.out.println("受影响的行数为:" + result);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
  • 条件的优先级

    **执行SQL:**UPDATE t_user SET user_name=?, email=? WHERE is_deleted=0 AND (age > ? AND user_name LIKE ? OR email IS NULL)

    public void test04(){
        //将(年龄大于20并且用户名中包含有a)或邮箱为null的用户信息修改
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.gt("age",20).like("username","a").or().isNull("email");
        User user = new User();
        user.setName("Oz");
        user.setEmail("test@oz6.com");
    
        int result = userMapper.update(user, updateWrapper);
        System.out.println(result > 0 ? "修改成功!" : "修改失败!");
        System.out.println("受影响的行数为:" + result);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    补充:

    原符号       <       <=      >       >=      <>
    对应函数    lt()     le()    gt()    ge()    ne()
        	less than       greater than      not equal
    
    1
    2
    3

    **执行SQL:**UPDATE t_user SET username=?, email=? WHERE is_deleted=0 AND (username LIKE ? AND (age > ? OR email IS NULL))

    public void test05(){
        //将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.like("username","a").and(i->i.gt("age",20).or().isNull("email"));
        User user = new User();
        user.setName("Vz7797");
        user.setEmail("test@ss8o.com");
    
        int result = userMapper.update(user, updateWrapper);
        System.out.println(result > 0 ? "修改成功!" : "修改失败!");
        System.out.println("受影响的行数为:" + result);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • 组装select子句

    **执行SQL:**SELECT username,age,email FROM t_user WHERE is_deleted=0

    public void test06(){
        //查询用户的用户名、年龄、邮箱信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("username","age","email");
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        maps.forEach(System.out::println);
    }
    
    1
    2
    3
    4
    5
    6
    7
  • 实现子查询

    **执行SQL:**SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (uid IN (select uid from t_user where uid <= 100))

    public void test07(){
        //查询id小于等于100的用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("uid", "select uid from t_user where uid <= 100");
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    
    1
    2
    3
    4
    5
    6
    7

# UpdateWrapper

UpdateWrapper不仅拥有QueryWrapper的组装条件功能,还提供了set方法进行修改对应条件的数据库信息

public void test08(){
    //将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.like("username","a").and( i -> i.gt("age",20).or().isNull("email")).set("email","svip@qq.com");
    //int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
    int result = userMapper.update(null, updateWrapper);
    System.out.println(result > 0 ? "修改成功!" : "修改失败!");
    System.out.println("受影响的行数为:" + result);
}
1
2
3
4
5
6
7
8
9

# condition

在真正开发的过程中,组装条件是常见的功能,而这些条件数据来源于用户输入,是可选的,因此我们在组装这些条件时,必须先判断用户是否选择了这些条件,若选择则需要组装该条件,若没有选择则一定不能组装,以免影响SQL执行的结果

  • 思路

    **执行SQL:**SELECT uid AS id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (user_name LIKE ? AND age <= ?)

    public void test10(){
        String username = "a";
        Integer ageBegin = null;
        Integer ageEnd = 30;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //Children like(boolean condition, R column, Object val);
        queryWrapper.like(StringUtils.isNotBlank(username), "user_name", username)
            .ge(ageBegin != null, "age", ageBegin)
            .le(ageEnd != null, "age", ageEnd);
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

# LambdaQueryWrapper

功能等同于QueryWrapper,提供了Lambda表达式的语法可以避免填错列名。

public void test11(){
    String username = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.like(StringUtils.isNotBlank(username), User::getName, username)
        .ge(ageBegin != null, User::getAge, ageBegin)
        .le(ageEnd != null, User::getAge, ageEnd);
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}
1
2
3
4
5
6
7
8
9
10
11

# LambdaUpdateWrapper

功能等同于UpdateWrapper,提供了Lambda表达式的语法可以避免填错列名。

public void test12(){
    //将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
    LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.like(User::getName, "a")
        .and(i -> i.gt(User::getAge, 20).or().isNull(User::getEmail));
    updateWrapper.set(User::getName, "小黑").set(User::getEmail,"abc@atguigu.com");
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result:"+result);
}
1
2
3
4
5
6
7
8
9

# 常用插件:

# 分页插件

# 添加配置类MyBatisPlusConfig

@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 一般分页

@Test
public void testPage(){
    //new Page()中的两个参数分别是当前页码,每页显示数量
    Page<User> page = userMapper.selectPage(new Page<>(1, 2), null);
    List<User> users = page.getRecords();
    users.forEach(System.out::println);
}
1
2
3
4
5
6
7

# 自定义分页

返回值为Page类型,参数传入一个Page对象,其他就是正常的编写sql

1.在UserMapper接口中定义一个方法

Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);
1

2.在UserMapper.xml中编写SQL实现该方法

<select id="selectPageVo" resultType="User">
    select id,username as name,age,email from t_user where age > #{age}
</select>
1
2
3

3.测试

@Test
public void testPageVo(){
    Page<User> page = userMapper.selectPageVo(new Page<User>(1,2), 20);
    List<User> users = page.getRecords();
    users.forEach(System.out::println);
}
1
2
3
4
5
6

# 分页常用数据

  • pageNum:当前页的页码
  • pageSize:每页显示的条数
  • size:当前页显示的真实条数
  • total:总记录数
  • pages:总页数
  • prePage:上一页的页码
  • nextPage:下一页的页码
  • isFirstPage/isLastPage:是否为第一页/最后一页
  • hasPreviousPage/hasNextPage:是否存在上一页/下一页
  • navigatePages:导航分页的页码数
  • navigatepageNums:导航分页的页码,[1,2,3,4,5]

# MyBatisX插件

# 安装MyBatisX插件

打开IDEA,File-> Setteings->Plugins->MyBatisX,搜索栏搜索MyBatisX然后安装

image-20220522115718361

# 步骤:

  • 新建一个Spring Boot项目引入依赖(创建工程时记得勾选lombok及mysql驱动)

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>3.5.0</version>
    </dependency>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • 配置数据源信息

    spring:
      datasource:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
        username: root
        password: 
    
    1
    2
    3
    4
    5
    6
    7
  • 在IDEA中与数据库建立链接

    image-20220522120758740

  • 填写数据库信息并保存

    image-20220522121434468

  • 找到我们需要生成的表点击右键

    image-20220522121613909

  • 填写完信息以后下一步

    image-20220522122127649

  • 继续填写信息

    image-20220522122525598

  • 大功告成

    image-20220522122612334

# 快速生成CRUD

MyBaitsX可以根据我们在Mapper接口中输入的方法名快速帮我们生成对应的sql语句(Alt+Enter)

image-20220522123143852

image-20220522123202310

红色高跟鞋
峰源萨克斯