Java从坚持到精通-MyBatisPlus

目录

1.MyBatisPlus简介

2.MyBatisPlus入门操作

3.MP开启日志

4.MP的自动映射规则

5.表映射

6.字段映射

7.QueryWrapper与LambdaQueryWrapper

8.分组查询

9.聚合查询

10.排序查询

11.内嵌逻辑查询

12.自定义条件查询

13.last方法

14.exists方法与notExists方法

15.主键策略

16.分页插件

17.ActiveRecord模式

18.SimpleQuery工具类

19.逻辑删除

20.通用枚举

21.字段类型处理器

22.自动填充功能

23.防止全表更新拦截器

24.MyBatisX及逆向工程

​编辑25.悲观锁和乐观锁

悲观锁

乐观锁

MP中的乐观锁使用

26.代码生成器

27.SQL分析打印


1.MyBatisPlus简介

主要就是简化MyBatis开发。

2.MyBatisPlus入门操作

1.引入依赖:需要引入mp和mysql驱动依赖。

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

2.编写配置文件,主要是数据库连接信息

spring:
  profiles:
    active: dev
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/duolaimi?serverTimezone=GMT%2B8
    username: root
    password: root

注意:有些版本的jdbc连接数据库的地址后面必须要加上时区,如serverTimezone=GMT%2B8,不加就会启动报错

3.mapper层

原来的mapper接口需要继承BaseMapper并传入对应的泛型即可,BaseMapper中包含了基本的增删改查方法。

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

4.service层

原来的service接口继承IService,并传入对应的泛型即可,IService里面也包含了基础的增删改查的业务方法。

public interface UserService extends IService<User> {
}

5.serviceimpl层

serviceimpl类需要实现原来定义好的service接口,但是只是实现了却没有重写必须的方法,所以需要继承ServiceImpl类,其中需要传两个泛型,第一个泛型是mapper接口,第二个泛型是实体类

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

6.编写controller

注入service对象,然后直接调用增删改查方法即可。

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/test")
    public String test(){
        User user = userService.getById(1);
        System.out.println(user);
        return user.toString();
    }

}

3.MP开启日志

直接使用如下配置即可开启日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

开启日志后,每次对数据库进行操作时,会有如下信息输出:

4.MP的自动映射规则

1.表名和实体类名映射,比如user表对应User实体类

2.字段名和实体类属性名映射,如字段名name对应实体类属性名name(getXxx或者setXxx)

3.属性映射默认支持小驼峰命名方式

5.表映射

1.如果表名与实体类名不一致,则可以使用@TableName("xxx")这个注解手动指定映射关系

2.如果每张表都有固定前缀的话,我们可以开启全局配置,使用如下配置指定表名的前缀

mybatis-plus:
  global-config:
    db-config:
      table-prefix: xxx_

6.字段映射

如果数据库字段与类中的属性名不一样,可以直接在属性上使用@TableFiled指定数据库字段名称

    @TableField("xxx")
    private String name;

如果字段或者属性是数据库中的关键字,则可以在@TableField中使用``(飘号)包起来。

如果希望被查询的字段不展示,则可以在@TableField使用select=false属性

如果数据库中的字段不存在,但是实体对象中有属性,可以使用@TableField中的exist=false属性

7.QueryWrapper与LambdaQueryWrapper

这两个是构建条件查询的对象,QueryWrapper后面的参数通过字符串传入,LambdaQueryWrapper可通过lambda表达式传入,写法上更优雅

如果是多条件查询,可以使用两种方法:

1.LambdaQueryWrapper里的条件方法,一直拼条件

2.QueryWrapper里的allEq()方法,参数传map

方法说明:

  • eq:等值查询
  • ne:不等查询
  • gt:大于查询
  • ge:大于等于查询
  • lt:小于查询
  • le:小于等于查询
  • between:区间查询
  • notBetween:不在区间查询
  • like:模糊查询
  • notLike:不包含查询
  • likeLeft:左包含查询
  • likeRight:右包含查询
  • isNull:空值查询
  • isNotNull:非空值查询
  • in:包含查询
  • notIn:不包含查询
  • inSql:包含查询,只不过后面的参数会将传入的sql整个放入in后面
  • notInSql:不包含查询,后面传sql字符串的方式

8.分组查询

分组查询一般使用QueryWrapper来进行封装数据

    @Test
    public void test3(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.groupBy("age");
        queryWrapper.select("age, count(*) as field_count");
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        System.out.println(maps);
    }

查看输出语句我们可以知道,groupBy()中的参数是指拼接在sql后面的group by的值,select()参数是指在sql中select后面的值。

9.聚合查询

在原来的分组查询基础上,如果再加上having查询,可使用如下语句:

queryWrapper.having("field_count >= 2");

10.排序查询

最终会在执行的sql后面拼上order by xxx

  • orderByAsc:根据指定字段升序
  • orderByDesc:根据指定字段降序
  • orderBy:其中有三个参数,参数1:如果排序字段的值为null的时候,是否还要作为排序字段参与排序 参数2:是否是升序排序 参数3:排序字段

11.内嵌逻辑查询

        queryWrapper.func(e -> {
           if(1 == 1){
               e.eq("name","zhangsan");
           }
        });

可以使用queryWrapper的func方法,做一些条件的分支。

12.自定义条件查询

可以使用queryWrapper的apply方法。

13.last方法

last方法会在最后执行,所以一般是做分页查询,如last("limit 0,2");

14.exists方法与notExists方法

exists()表示参数里面如果能返回结果,则外面的sql会执行,否则不执行,notExists则相反。

15.主键策略

可以使用@TableId注解声明这是一个主键字段,并设置type属性,type属性有如下几种类型:

  • AUTO:该策略为跟随数据库表的主键按递增策略,前提是数据库表的主键要设置为自增
  • INPUT:必须由武松们手动插入主键,否则无法添加数据
  • ASSIGN_ID:使用雪花算法生成一个唯一的id,64位二进制,19位长度的十进制
  • NONE:不指定主键生成策略,跟随全局策略
  • ASSIGN_UUID:UUID的主键,32位数字组成,编码采用16进制

如果我们不设置主键策略,则默认是使用雪花算法

16.分页插件

需要配置拦截器,并指定数据库类型(3.4版本及之后)

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }

}

 注意,不同版本的MyBatisPlus的分页配置是不一样的。

如果是3.4版本之前的是如下配置:

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

}

使用分页:

    @Test
    public void test4(){
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        Page<User> userPage = new Page<>(1, 10);

        userMapper.selectPage(userPage, lambdaQueryWrapper);

        List<User> records = userPage.getRecords();

    }

使用Page对象,在构造方法上指定页数和每页显示条数,然后使用生成的selectPage方法,不需要接收返回值,直接在原来声明好的page对象中就能接收分页信息。

自定义分页方法:

我们可以在声明方法的时候,传参传IPage对象,返回值也返回IPage对象

17.ActiveRecord模式

ActiveRecord(活动记录,简称AR),是一种领域模型模式,特点是一个模型类对应的关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

如何使用?

原有的实体类继承Model,并指定泛型即可,里面有基本的增删改查方法。

@Data
public class User extends Model<User> {

    private Long id;
    private String name;
    private Long age;
    private String email;

}


    @Test
    public void test5(){
        User user = new User();
        user.insert();
    }

18.SimpleQuery工具类

SimpleQuery可以对selectList查询后的结果用Stream流进行一些封装,使其但会一些指定给结果,简洁了api的调用。

基本方法:

  • list:返回一个list集合,存放符合条件的(第一个参数),并且第二个参数属性的集合
  • keyMap:返回一个map对象,key为第二个参数类型的值,value为第一个参数类型中泛型类型的值
  • group:返回一个map,其中key是第二个参数类型的数据,value是实体类型的集合

19.逻辑删除

逻辑删除的操作是增加一个字段表示这个数据的状态,如果一条数据需要删除,我们通过改变这条数据的状态来实现,这样既可以表示这条数据是删除的状态,又保留了数据以便以后统计。

如何实现?

数据表中加上一个字段,表示逻辑删除,如status(int类型),0删除-1未删除

然后在类的属性上加上@TableLogic注解,其中属性value表示未删除的状态,delvalue表示删除的状态

以后再删除数据的时候,其实是更新状态。
再查询数据的时候,后面会加上status的条件

也可以在配置文件中设定全局逻辑删除的配置

主要设定逻辑删除属性,有效值和被删除值

这里如果配置了全局逻辑删除字段,但实体类中如果没有该字段,其实也不会报错,就不会走逻辑删除

20.通用枚举

如果我们需要插入枚举中具体的值,但又不希望在代码中直接获取到值去插入,我们只希望声明到枚举,这时候我们可以使用@EnumValue注解来声明传递枚举时需要传递这个值。

21.字段类型处理器

在某些场景下,我们在实体类中是使用Map集合作为属性接收前端传递过来的数据的,但是这些数据在数据库时,我们使用的是json格式的数据进行存储,json本质是一个字符串,就是varchar类型。那怎么做到实体类的Map类型和数据库的varchar类型的互相转换,这里就需要使用到字段类型处理器来完成。

如何使用?

1.项目中需要添加fastjson依赖坐标

2.数据库加字段对应和实体类加上属性, 数据库字段是varchar类型,实体类属性是String类型

3.在实体类属性上标注@TableField注解,并指定转换器,说明往数据表中存的数据将要转换成json格式

4.在实体类上加上@TableName注解,并设置json自动转换成map,这会将数据表中读到的json自动转换成map

22.自动填充功能

在项目中有一些属性,如果我们不希望每次都填充的话,我们可以设置为自动填充,比如常见的时间,创建时间和更新时间可以设置为自动填充。

1.我们可以使用@TableField注解,指定fill属性,说明该字段在新增还是更新时做插入

2.编写填充策略处理器

@Component
public class MyMetaHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        setFieldValByName("createTime", new Date(), metaObject);
        setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        setFieldValByName("updateTime", new Date(), metaObject);
    }
}

指定要填充的字段和填充的数据。

23.防止全表更新拦截器

只需在mybatis的配置类中添加一个防止全表更新的拦截器即可,如果出现全表更新操作,则会抛出异常。

24.MyBatisX及逆向工程

我么可以在idea的插件中安装mabatisX的插件,安装完毕后,通过idea连接数据库,然后右击表名,第一个会出现MyBatisX Generator,也就时MyBatisX的代码生成器插件。

在弹出的框中,我们一般做如下配置:

设置模块地址,设置包名,设置表前缀(没有前缀则可以不用设置)

选择mp3版本,使用lombok,设置mapper.xml路径

可以根据名字自动生成更复杂的查询,然后选择生成即可。


25.悲观锁和乐观锁

悲观锁

悲观锁实在查询的时候就锁定数据,在这次请求未完成之前,不会释放锁。等到这次请求完毕之后,再释放锁,释放了锁以后,其他请求才能对这条数据完成读写

这样做的操作能够保证读取到的信息就是当前的信息,保证了信息的正确性,但是并发效率很低,在实际开发中使用悲观锁的场景很少,因为在并发时我们是要保证效率的。

乐观锁

乐观锁是通过表字段完成设计的,他的核心思想是,在读取的时候不加锁,其他请求依然可以读取到这个数据,在修改的时候判断一个数据是否有被修改过,如果有被修改过,那本次请求的修改失效。

MP中的乐观锁使用

1.数据表新增一个字段,比如version,int类型,设置默认值为1

2.在属性上添加@Version注解

3.添加拦截器,看名字就知道是乐观锁拦截器

26.代码生成器

mp的代码生成器区别于mybatisX插件,更加灵活。

如何使用?

1.引入必要依赖

2.查看官网,我们可以在main方法中添加固定代码,根据自己配置稍作配置即可

FastAutoGenerator.create("url", "username", "password")
    .globalConfig(builder -> {
        builder.author("baomidou") // 设置作者
            .enableSwagger() // 开启 swagger 模式
            .fileOverride() // 覆盖已生成文件
            .outputDir("D://"); // 指定输出目录
    })
    .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
        int typeCode = metaInfo.getJdbcType().TYPE_CODE;
        if (typeCode == Types.SMALLINT) {
            // 自定义类型转换
            return DbColumnType.INTEGER;
        }
        return typeRegistry.getColumnType(metaInfo);

    }))
    .packageConfig(builder -> {
        builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
            .moduleName("system") // 设置父包模块名
            .pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径
    })
    .strategyConfig(builder -> {
        builder.addInclude("t_simple") // 设置需要生成的表名
            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
    })
    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
    .execute();

27.SQL分析打印

我们在日常开发中,避免不了查看当前程序锁所执行的SQL语句,以及了解它的执行时间,方便分析是否出现了慢SQL问题。我们可以使用MyBatisPlus提供的SQL分析打印的功能,来获取SQL语句执行的时间。

如何使用?

1.引入坐标,p6spy

2.在配置文件中配置信息

3.在resources下,创建spy.properties配置文件,配置代码基本固定

4.测试

在接下来的sql执行中,会提示输出红色文字,展示sql耗时

  • 36
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值