mybatis-plus

编写代码

配置(spring boot 2.1及以上(内置jdbc8驱动)

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bigdata?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=952700

启动类(添加 @MapperScan 注解,扫描 Mapper 文件夹)

@SpringBootApplication
@MapperScan("com.chengzi.demomptest.mapper")
public class DemompTestApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemompTestApplication.class, args);
    }
}

添加mapper

@Repository
public interface UserMapper extends BaseMapper<User> {
}

查看sql输出日志

#mybatis 日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

主键策略

插入操作

@Test
void testAdd(){
    User user = new User();
    user.setName("chengzi");
    user.setAge(18);
    user.setEmail("123@qq.com");
    // 返回值是影响的行数
    int insert = userMapper.insert(user);
    System.out.println(insert);
}

MP的主键策略

ASSIGH_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)19位

 ASSIGN_UUID 19位  AUTO(自动增长) INPUT(自己set)

@TableId(type = IdType.ASSIGN_ID)
private String id;

要想影响所有实体的配置,可以设置全局主键配置 

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

自动填充和乐观锁

更新操作

注意:update是生成的sql自动是动态sql:update user set age = ?where id = ?

// 修改
@Test
void testUpdate(){
    User user = new User();
    user.setId(1932410622691172353L);
    user.setName("xigua");
    // 返回值是影响的行数
    int count = userMapper.updateById(user);
    System.out.println(count);
}

自动填充

需求描述:项目中经常遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。

我们可以使用Mybatis Plus的自动填充功能,完成这些字段的赋值操作

实体类修改

// 实体上增加字段并添加自动填充注解
// 添加的时候设置值
@TableField(fill = FieldFill.INSERT)
private Data createTime;
// 添加和修改的时候设置值
@TableField(fill = FieldFill.INSERT_UPDATE)
private Data updateTime;

实现元对象处理器接口

注意:不要忘记添加 @Component 注解

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // MP执行添加操作,这个方法执行
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    // MP执行修改操作,这个方法执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

乐观锁

场景

主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新

乐观锁实现方式:

取出记录时,获取当前version

更新时,带上这个version

执行更新时, set version = newVersion where version = oldVersion

如果version不对,就更新失败

接下来介绍如何在Mybatis-Plus项目中,使用乐观锁

乐观锁实现流程

修改实体类

添加 @Version 注解

@Version
private Integer version;

创建配置文件

创建包config,创建文件MybatisPlusConfig.java

此时可以删除主类中的 @MapperScan 扫描注解

/**
* 乐观锁插件
*/
@Configuration
@MapperScan("com.chengzi.demomptest.mapper")
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 添加乐观锁插件
        return interceptor;
    }
}

查询

通过多个id批量查询

完成了动态sql的foreach的功能  

// 多个id批量查询
@Test
void testSelect1() {
    userMapper.selectBatchIds(Arrays.asList(1, 2, 3)).forEach(System.out::println);
}

简单的条件查询

通过map封装查询条件

注意:map中的key对应数据库中的列名。如:数据库user_id,实体类是userId,这时map的key需要填写user_id

// 简单条件查询
@Test
void testSelect2() {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "Jack");
    map.put("age", 20);
    userMapper.selectByMap(map).forEach(System.out::println);
}

分页

分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

添加分页插件

配置类中添加@Bean配置

@Configuration
public class MyBatisPlusConfig {
    /**
     * 分页插件(3.4.0+ 版本使用 MybatisPlusInterceptor 统一管理插件)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 添加分页插件(核心)
        PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
        
        // 可选配置:设置分页参数
        paginationInterceptor.setMaxLimit(500L); // 单页最大限制数量,默认 500 条,-1 表示不限制
        paginationInterceptor.setDbType(DbType.MYSQL); // 指定数据库类型(自动识别时可省略)
        
        interceptor.addInnerInterceptor(paginationInterceptor);
        return interceptor;
    }
}

编写分页代码

  1. 插件Page对象,传入两个参数:当前页、每页记录数
  2. 调用mp的方法实现分页
// 分页查询
@Test
void testSelectPage() {
    Page<User> page = new Page<>(1, 5);
    Page<User> userPage = userMapper.selectPage(page, null);
    // 返回对象得到分页中的所有数据
    long pages = userPage.getPages(); // 总页数
    System.out.println("总页数:" + pages);
    long current = userPage.getCurrent(); // 当前页
    System.out.println("当前页:" + current);
    List<User> records = userPage.getRecords(); // 当前页数据
    records.forEach(System.out::println);
    long total = userPage.getTotal(); // 总记录数
    System.out.println("总记录数:" + total);
    boolean hasPrevious = userPage.hasPrevious(); // 是否有上一页
    System.out.println("是否有上一页:" + hasPrevious);
    boolean hasNext = userPage.hasNext(); // 是否有下一页
    System.out.println("是否有下一页:" + hasNext);
}

删除与逻辑删除

删除

根据id删除记录

// 根据id删除
@Test
void testDelete() {
    int i = userMapper.deleteById(1932430505864773634L);
    System.out.println(i);
}

批量删除

// 根据id批量删除
@Test
void testDeleteBatchIds() {
    int i = userMapper.deleteBatchIds(Arrays.asList(1, 2, 3));
    System.out.println(i);
}

简单条件删除

//简单条件删除
@Test
public void testDeleteByMap() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "Helen");
    map.put("age", 18);
    int result = userMapper.deleteByMap(map);
    System.out.println(result);
}

逻辑删除

物理删除和逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

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

逻辑删除的使用场景:

可以进行数据恢复

有关联数据,不便删除

逻辑删除实现流程

数据库修改

添加 deleted字段

ALTER TABLE `user` ADD COLUMN `deleted` boolean DEFAULT false
实体类修改

添加deleted 字段,并加上 @TableLogic 注解

@TableLogic
private Integer deleted;
配置(可选)

application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

条件构造器和常用接口

wapper介绍

 

Wrapper : 条件构造抽象类,最顶端父类  

    AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

        QueryWrapper : 查询条件封装

        UpdateWrapper : Update 条件封装

    AbstractLambdaWrapper : 使用Lambda 语法

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

        LambdaUpdateWrapper : Lambda 更新封装Wrapper 

测试用例

ge 大于等于、gt 大于、le 小于等于、lt 小于、isNull 空、isNotNull 非空

@Test
public void testQuery() {
    QueryWrapper<User>queryWrapper = newQueryWrapper<>();
    queryWrapper
        .isNull("name")
        .ge("age", 12)
        .isNotNull("email");
    int result = userMapper.delete(queryWrapper);
    System.out.println("delete return count = " + result);
}

 eq 等于、ne 不等于

注意:seletOne()返回的是一条实体记录,当出现多条时会报错

@Test
public void testSelectOne() {
    QueryWrapper<User>queryWrapper = newQueryWrapper<>();
    queryWrapper.eq("name", "Tom");
    Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
    System.out.println(user);
}

between、notBetween

包含大小边界

@Test
public void testSelectCount() {
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper.between("age", 20, 30);
    Long count = userMapper.selectCount(queryWrapper);
    System.out.println(count);
}

like、notLike、likeLeft、likeRight

selectMaps()返回Map集合列表,通常配合select()使用

@Test
public void testSelectMaps() {
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper
            .select("name", "age")
            .like("name", "e")
            .likeRight("email", "5");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
    maps.forEach(System.out::println);
}

 orderBy、orderByDesc、orderByAsc

@Test
public void testSelectListOrderBy() {
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByDesc("age", "id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

 查询方式

查询方式

说明

setSqlSelect

设置 SELECT 查询字段

where

WHERE 语句,拼接 + WHERE 条件

and

AND 语句,拼接 + AND 字段=值

andNew

AND 语句,拼接 + AND (字段=值)

or

OR 语句,拼接 + OR 字段=值

orNew

OR 语句,拼接 + OR (字段=值)

eq

等于=

allEq

基于 map 内容等于=

ne

不等于<>

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

like

模糊查询 LIKE

notLike

模糊查询 NOT LIKE

in

IN 查询

notIn

NOT IN 查询

isNull

NULL 值查询

isNotNull

IS NOT NULL

groupBy

分组 GROUP BY

having

HAVING 关键词

orderBy

排序 ORDER BY

orderAsc

ASC 排序 ORDER BY

orderDesc

DESC 排序 ORDER BY

exists

EXISTS 条件语句

notExists

NOT EXISTS 条件语句

between

BETWEEN 条件语句

notBetween

NOT BETWEEN 条件语句

addFilter

自由拼接 SQL

last

拼接在最后,例如:last(“LIMIT 1”)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值