MyBatis-Plus 快速上手 (springboot快速集成mybatis-plus)

学习笔记及梳理来自尚硅谷Hellen老师视频观后感

1.简介

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。详情见官网,关键之处在特性。

  • 润物无声
    只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
  • 效率至上
    只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。
  • 丰富功能
    热加载、代码生成、分页、性能分析等功能一应俱全

2.框架结构

MP框架

3.快速配置环境

  • 导入依赖
<!--mybatis-plus-->
 		<!--引入MP后就不要再引入Mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>
        <!--mysql运行时依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--lombok,第一次使用时记得安装插件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
  • 配置application.properties文件,yml会更加合适
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
  • 在主类中添加@MapperScan注解,也可以自己写一个MP的配置类
@MapperScan("com.springboot.mybatis_plus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

到此这三步已经完成了MP的配置!

4.测试CRUD

  • 随便写一个实体类测试一下
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  • 创建mapper包,编写Mapper接口UserMapper
//IDEA在 userMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。
 //为了避免报错,可以在 dao 层 的接口上添加 @Repository 
@Repository
public interface UserMapper extends BaseMapper<User> {
//继承的BaseMapper类中有许多现成的CRUD方法,非常好用
}

接下来就可以进行注入测试了

  • 测试CRUD
@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;
    @Test
    void testSelectList() {
        //UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper
        //所以不填写就是无任何条件
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
        //查询指定id
        User user = userMapper.selectById(1);
        System.out.println(user);
    }
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("ly").setAge(22).setEmail("578104130@qq.com");
        int insert = userMapper.insert(user);
        System.out.println("影响的行数" + insert);
        System.out.println("id" + user);
    }
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId((long) 7).setName("wxy");
        int insert = userMapper.updateById(user);
        System.out.println("影响的行数" + insert);
        System.out.println("id" + user);
    }
    @Test
    public void testDeleteById(){
        int result = userMapper.deleteById(5L);
        System.out.println(result);
    }
}

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

5.MP的特性

1) 主键策略

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法),具体还有哪些主键策略,可以点进去IdType查看

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

AUTO 自增策略,需要在创建数据表的时候设置主键自增,实体字段中配置 @TableId(type = IdType.AUTO)

@TableId(type = IdType.AUTO)
private Long id;

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

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

2) 自动填充

实体类添加字段并添加自动填充注解

//自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    //@TableField(fill = FieldFill.UPDATE)
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

实现元对象处理器接口

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
    //首次插入的时候为两个字段赋值
        this.setFieldValByName("createTime", new Date(), metaObject);

        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    //更新的时候只需要修改updateTime
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

这样就实现了创建时间和修改时间的自动填充功能

3) 乐观锁插件

锁大家一定不陌生,当不同的用户同时读写同一份数据的时候,就会出现很多问题。锁分为两种,悲观锁(用户一处理数据就封锁住,不让其他人操作)和乐观锁(通过给数据加版本号)。

实现步骤

  • 数据库中添加version字段
  • 取出记录时,获取当前version
  • 更新时,version + 1,如果where语句中的version版本不对,则更新失败

具体实现

  • 修改实体类,添加 @Version 注解
@Version
private Integer version;
  • 创建MP的配置文件并注册乐观锁到IOC容器中
@Configuration
@MapperScan("com.springboot.mybatis_plus.mapper")//可以将主启动类的扫描包配置在这里
public class MyBatisPlusConfig {

    //乐观锁插件,本质为拦截器,加@Version注解
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

4) 分页插件

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

  • 添加分页插件,配置类中添加@Bean配置
//分页插件,本质为拦截器
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
  • 测试
@Test
public void testSelectPage() {
    Page<User> page = new Page<>(1,5);
    Page<User> pageParam = userMapper.selectPage(page, null);
    pageParam.getRecords().forEach(System.out::println);
    
    System.out.println(pageParam.getCurrent());
    System.out.println(pageParam.getPages());
    System.out.println(pageParam.getSize());
    System.out.println(pageParam.getTotal());
    System.out.println(pageParam.hasNext());
    System.out.println(pageParam.hasPrevious());
}

结果如下
在这里插入图片描述

5) 逻辑删除(假删除)

  • user表添加 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
  • 测试后发现,数据并没有被删除,deleted字段的值由0变成了1,测试后分析打印的sql语句,是一条update语句

注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

6.条件构造器

  • 类图(该图来自尚硅谷Helen老师的讲义)
    Wrapper类图
    Wrapper : 条件构造抽象类,最顶端父类
    AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
    QueryWrapper : 查询条件封装
    UpdateWrapper : Update 条件封装
    AbstractLambdaWrapper : 使用Lambda 语法
    LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
    LambdaUpdateWrapper : Lambda 更新封装Wrapper
  • 测试

1)ge、gt、le、lt、isNull、isNotNull

@Test

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

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

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

3)between、notBetween 包含大小边界

@Test
public void testSelectCount() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.between("age", 20, 30);
    Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
    System.out.println(count);
}

4)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);
}

5)in、notIn、inSql、notinSql、exists、notExists

  • notIn(“age”,{1,2,3})—>age not in (1,2,3)
  • 实现子查询
  • inSql(“id”, “select id from table where id < 3”)—>id in (select id from table where id < 3)
@Test
    public void testSelectObjs() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        queryWrapper.in("id", 1, 2, 3);
        queryWrapper.inSql("id", "select id from user where id <= 3");
        List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
        objects.forEach(System.out::println);
    }

6)or、and

注意:这里使用的是 UpdateWrapper 不调用or则默认为使用 and 连

@Test
public void testUpdate1() {
    //修改值
    User user = new User();
    user.setAge(99);
    user.setName("Andy");
    //修改条件
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    userUpdateWrapper
        .like("name", "h")
        .or()
        .between("age", 20, 30);
    int result = userMapper.update(user, userUpdateWrapper);
    System.out.println(result);
}

7)lambda表达式,lambda表达式内的逻辑优先运算

@Test

public void testUpdate2() {
    //修改值
    User user = new User();
    user.setAge(99);
    user.setName("Andy");
    //修改条件
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    userUpdateWrapper
        .like("name", "n")
        .or(i -> i.like("name", "a").eq("age", 20));
    int result = userMapper.update(user, userUpdateWrapper);
    System.out.println(result);
}

8)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);
}

9)set、setSql,最终的sql会合并 user.setAge(),以及userUpdateWrapper.set() 和 setSql() 中 的字段

@Test
public void testUpdateSet() {
    //修改值
    User user = new User();
    user.setAge(60);
    //修改条件
    UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
    userUpdateWrapper
        .like("name", "h")
        .set("name", "Peter")//除了可以查询还可以使用set设置修改的字段
        .setSql(" email = '123@qq.com'");//可以有子查询
    int result = userMapper.update(user, userUpdateWrapper);
}

分页

	// 方法一
	Page<User> page = new Page<>(2,5);
	userMapper.selectPage(page, null)
	page.getRecords().forEach(System.out::println);
	System.out.println(page.getTotal());

	// 方法二
 QueryWrapper<UniversityEntity> wrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(key)) {
            wrapper.eq("u_id",key)
                    .or().like("u_code",key)
                    .or().like("u_name", key)
                    .or().like("province",key);
        }

        IPage<UniversityEntity> page = this.page(new Query<UniversityEntity>().getPage(params,"sort",true), wrapper);
        //TODO 返回的totalCount为0
        return new PageUtils(page);

7) 查询方式

查询方式说明
setSqlSelect设置 SELECT 查询字段
whereWHERE 语句,拼接 + WHERE 条件
andAND 语句,拼接 + AND 字段=值
andNewAND 语句,拼接 + AND (字段=值)
orOR 语句,拼接 + OR 字段=值
orNewOR 语句,拼接 + OR (字段=值)
eq等于=
allEq基于 map 内容等于=
ne不等于<>
gt大于>
ge大于等于>=
lt小于<
le小于等于<=
like模糊查询 LIKE
notLike模糊查询 NOT LIKE
inIN 查询
notInNOT IN 查询
isNullNULL 值查询
isNotNullIS NOT NULL
groupBy分组 GROUP BY
havingHAVING 关键词
orderBy排序 ORDER BY
orderAscASC 排序 ORDER BY
orderDescDESC 排序 ORDER BY
existsEXISTS 条件语句
notExistsNOT EXISTS 条件语句
betweenBETWEEN 条件语句
notBetweenNOT BETWEEN 条件语句
addFilter自由拼接 SQL
last拼接在最后,例如:last(“LIMIT 1”)

更多技术博客请关注微信公众号:WHICH工作室
WHICH工作室

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅贝勒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值