【MyBatis-Plus】快速入门

举报
向阳花花花花 发表于 2023/07/27 09:43:11 2023/07/27
【摘要】 本文主要讲解mybatis-plus快速入门。

一、快速入门

1.1 入门案例

入门案例制作步骤:

(1)新建模块并导入mybatis-plus起步依赖

<!--        mybatis-plus起步依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
<!--        lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <!--        druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.10</version>
        </dependency>

(2)编写application.yml文件

server:
  port: 8080
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false
    username: root
    password: 123456

# mybatis-plus日志

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

(3)根据数据库表字段新建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;

}

(4)编写mapper接口并测试查看运行结果

@Mapper
public interface UserMapper extends BaseMapper<User> {
// 没有写任何接口方法
}

@SpringBootTest
class Demo1ApplicationTests {

    @Autowired
    private UserMapper mapper;
    
    @Test
    public void contextLoads() {
//        测试查询全部
        List<User> users = mapper.selectByMap(null);
        System.out.println(users);
    }

}

1.2 简介

Mybatis-Plus(简称MP)是基于Mybatis框架基础上开发的增强型工具,旨在简化开发,提高效率。mybatis-plus官网mybatis-plus

MybatisPlus特性
无侵入:只做增强不做改变
强大的CRUD操作:内置通用Mapper,少量配置即可实现单表CRUD操作
支持Lambda:编写查询条件无需担心字段写错
内置分页查询
支持主键自动生成

二、标准CRUD制作

2.1 CRUD操作


@SpringBootTest
class MybatisPlus1ApplicationTests {

    @Autowired
    private UserMapper mapper;

    @Test
    public void testUserMapper() {
        
//        查询所有
        List<User> users = mapper.selectByMap(null);
        System.out.println(users);
    }

    /**
     * 测试添加操作
     * 对于自增的字段:如果没有设置,则自动生成一个值;
     * 对于非自增字段:如果可以为空,不生成;如果不可以为空,报错。
     */
    @Test
    public void insert() {
        User user = new User();
        user.setId(3L);
        user.setName("sesssok");
        user.setPassword("1333");
        user.setAge(3);
        int i = mapper.insert(user);
        System.out.println(i);
    }

    /**
     * 测试删除操作
     */
    @Test
    public void delete() {
//        批量删除--
//        (Collection接口下有set、list、queue三个接口)根据id删除
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        mapper.deleteBatchIds(list);
//        根据map对象删除-根据某个字段删除
        Map map = new HashMap();
        map.put("age", 23);
        mapper.deleteByMap(map);
    }

    /**
     * 测试修改操作
     */
    @Test
    public void update() {
        User user = new User();
        user.setId(3L);
        user.setAge(19);
//        修改所有
//        mapper.update();
//        根据id修改
        int i = mapper.updateById(user);
        System.out.println(i);
    }
}

下面是核心接口,附上源码和注释:


public interface BaseMapper<T> extends Mapper<T> {
//    插入一条记录
    int insert(T entity);

//    根据id删除
    int deleteById(Serializable id);

//    将map中的元素设置为删除的条件,多个条件之间是AND关系
    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

//    将实体对象进行封装,包装为删除条件(类似上面)
    int delete(@Param("ew") Wrapper<T> queryWrapper);

//    根据id集合批量删除
    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

//    根据id更新
    int updateById(@Param("et") T entity);

//    根据条件更新,Wrapper是条件
    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

//    根据id查询
    T selectById(Serializable id);

//    根据id(ids)批量查询
    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

//    根据键值查询
    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

//    根据实体条件查询一个,如果查到多个,就会报错
    T selectOne(@Param("ew") Wrapper<T> queryWrapper);

//    条件查询总记录数
    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

//    条件查询集合
    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

//    条件查询map集合
    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

//    分页查询
    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}

2.2 分页查询

配置分页插件:

@Configuration
public class MpConfig {

    /**
     * 设置Mybatis-Plus可以使用分页功能的插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor interceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

调用分页方法并查看测试结果:

    /**
     * 测试分页
     */
    @Test
    public void testPage() {
        IPage page = new Page();
        page.setCurrent(1); // 设置当前页码
        page.setSize(5); // 设置每页显示数
        mapper.selectPage(page, null);
        System.out.println("当前页码-->" + page.getCurrent() + ",每页显示数-->" + page.getSize());
        System.out.println("总页数-->" + page.getPages() + ",总记录数-->" + page.getTotal() + ",数据-->" + page.getRecords());
    }

三、DQL

3.1 3种查询条件格式

查询条件格式 使用QueryWrappe泛型类 使用QueryWrapper泛型类+lambda 使用LambdaQueryWrapper泛型类

(1)新建一个模块

(2)导入MyBatis-Plus相关依赖

		<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.2.10</version>
        </dependency>

(3)使用方法


@SpringBootTest
class Demo1ApplicationTests {

    @Autowired
    private UserMapper mapper;

    @Test
    public void testSelectCon1() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lt("age",20); // 查询age<20的记录
        System.out.println(mapper.selectList(wrapper));
    }

    @Test
    public void testSelectCon2() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.lambda().lt(User::getAge,20);
        System.out.println(mapper.selectList(wrapper));
    }


    @Test
    public void testSelectCon() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(User::getAge,20);
        System.out.println(mapper.selectList(wrapper));
    }

}
并列关系 或者关系
默认(.and()) .or()
    @Test
    public void testSelectCon4() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(User::getAge, 18).or();
        wrapper.gt(User::getAge, 20); // age<18 || age>20

        // 链式写法1--or
        wrapper.lt(User::getAge, 18).or()
                .gt(User::getAge, 20); // age<18 || age>20

        // 链式写法2--and
        wrapper.gt(User::getAge, 10).lt(User::getAge, 18); // age>18 && age<18
        System.out.println(mapper.selectList(wrapper));
        
    }

(4)在yml配置文件设置关闭mybati-plus和SpringBoot的banner图案

  # spring--banner: off
  main:
    banner-mode: off

# mybatis-plus--banner: false
mybatis-plus:
  global-config:
    banner: false

(5)新建logback.xml文件清除日志


  # 标准日志输出
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

上面的输出不利于我们调试代码,因此在yml文件中添加如上代码,使控制台输出相关日志。

3.2 空值判定

如果查询条件为空还出现在了Sql语句中,就会报错,要先使用null != __ 判断

(1)实体类和测试用例

@Data
public class QueryUser extends User{
    /**
     * 定义年龄范围的上限
     */
    private Integer ageGt;
}
   @Test
    public void testNull() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        QueryUser user = new QueryUser();
//        user.setAge(18); // 设置年龄下限
        user.setAgeGt(20); // 设置年龄上限
        wrapper.gt(User::getAge,user.getAge());
        wrapper.lt(User::getAge,user.getAgeGt());
        mapper.selectList(wrapper);
    }

(2)运行结果

(3)解决方案-在查询之前加入条件判定再查看SQL语句

wrapper.gt(null != user.getAge(), User::getAge, user.getAge());
wrapper.lt(null != user.getAgeGt(), User::getAge, user.getAgeGt());

3.3 条件设置

条件 等于 范围 模糊
表达 eq lt,le,gt,ge,eq,between like,likeLeft,likeRight(左右表示百分号的位置)

通过查看官方文档了解更多查询条件的用法——MyBatis-Plus条件构造器官网链接


举例:

   	@Test
    public void testSelectCon5() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(User::getAge, 19, 25); // 查询age>=19 && age<=25的数据
        mapper.selectList(wrapper);
        wrapper.like(User::getUsername, "s"); // %s%
        mapper.selectList(wrapper);
        wrapper.likeRight(User::getPassword, "ll"); // ll%
    }

3.4 字段映射匹配

情况 属性名和字段名不同 有些属性不在表中 有些字段不参与查询 实体类名和表名不同
映射@TableFiled value = “字段名” exist =false select = false @TableName(“”)
 /**
     * 用户名
     */
    @TableField("name") // 1.字段名为name
    private String username;

    /**
     * 密码
     */
    @TableField(select = false) // 3.不参与查询
    private String password;

    /**
     * 在线状态
     */
    @TableField(exist = false) // 2.不存在
    private Integer online;

四、DML

4.1 id生成策略

id生成策略 Auto Input Assign
使用 数据库定义一个id起始,然后+1 用户定义编写一个id 用雪花算法生成一个Long值,默认策略

(1)自定义id自增

@Test
    public void testId() {
        User user  =new User();
        user.setUsername("DemoQ");
        user.setPassword("WWER");
        user.setAge(20);
        mapper.insert(user); // 插入一条记录并查看id
    }



(2)默认生成的Id



(3)自定义Id

    @Test
    public void testId() {
        User user  =new User();
        user.setId(20L);
        user.setUsername("DemoQ");
        user.setPassword("WWER");
        user.setAge(20);
        mapper.insert(user); // 插入一条记录并查看id
    }


可以再yml文件中全局配置id生成策略,这样就不用写@TableId注解,配置表名前缀,不用写@TableName的前缀注解。

# mybatis-plus--banner: false
mybatis-plus:
  global-config:
    banner: false
    db-config:
      id-type: assign_id # 使用默认的id生成策略
      table-prefix: tb_ # 设置表名前缀,类名 = 表名-前缀
  # 标准日志输出
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4.2 多数据操作

这里主要通过两个API,deleteBatchIds(),selectBatchIds()来讲解多数据操作。

    @Test
    public void testMore() {
        List<Long> list = new ArrayList<>();
        list.add(5L);
        list.add(6L);
        mapper.selectBatchIds(list); // 批量查询
    }
    @Test
    public void testMoreDelete() {
        List<Long> list = new ArrayList<>();
        list.add(20L);
        list.add(27L);
        mapper.deleteBatchIds(list); // 批量删除
    }

4.3 逻辑删除

通过字段(通常叫deleted)标记数据是否可用,不是执行真的删除,而是执行修改。之后查询时,MyBatis-Plus的所有查询操作都只查询没有被逻辑删除的数据。

设置逻辑删除字段 @TableLogic() yml配置




执行删除操作之后再次查看表中数据:


4.4 乐观锁(update)


步骤:
(1)数据库表中添加version字段,用于标记版本

(2)实体类中添加相应的字段并添加@Version注解

(3)添加拦截器实现动态添加sql语句

@Configuration
public class MpConfig {
    
    @Bean
    public MybatisPlusInterceptor interceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 
        // 乐观锁拦截器
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

(4)模拟乐观锁version自增+1(执行更新操作前必须提前告知version版本)

法一:设置版本

    @Test
    public void testOptimisticLock() {
        User user = new User();
        user.setId(5L);
        user.setAge(33);
        user.setVersion(1);
        mapper.updateById(user);
    }

法二:通过id得到版本

    @Test
    public void testOptimisticLock2() {
        User user = mapper.selectById(6);
        user.setUsername("123");
        mapper.updateById(user);
    }

五、代码生成器

模板+配置=代码生成器
(1)导入模板生成器和模板引擎坐标

<!--        代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

(2)配置数据库连接信息和其他配置

注意这里配置的数据库信息不是用于增删改查,而是用于创建实体类等。


public class CodeGenerator {

    public static void main(String[] args) {

        /**
         * 基础配置
         */
        AutoGenerator generator = new AutoGenerator();
        DataSourceConfig config = new DataSourceConfig();  // 配置数据库连接相关信息
        config.setDbType(DbType.MYSQL);
        config.setDriverName("com.mysql.cj.jdbc.Driver");
        config.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false");
        config.setUsername("root");
        config.setPassword("123456");
        generator.setDataSource(config);

        /**
         * 设置全局配置
         */
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java"); // 指定生成的代码模板目录
        globalConfig.setAuthor("XiaoGuo"); // 设置作者
        globalConfig.setOpen(false); // 设置生成代码后是否打开目录
        globalConfig.setControllerName("%sController"); // 设置Controller文件名
        globalConfig.setFileOverride(true); // 设置文件覆盖
        globalConfig.setMapperName("%sMapper"); // 设置mapper层文件名
        globalConfig.setIdType(IdType.ASSIGN_ID); // 设置ID生成策略
        generator.setGlobalConfig(globalConfig);

        /**
         * 设置包名相关配置
         */
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.itxiaoguo"); // 设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
        generator.setPackageInfo(packageConfig);

        /**
         * 策略设置
         */
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tb_user"); // 设置要生成的表名,如果有多个,则叠加
        strategyConfig.setTablePrefix("tb_"); // 设置表前缀名,生成的=表名-前缀
        strategyConfig.setRestControllerStyle(true); // 生成的controller使用rest风格
        strategyConfig.setEntityLombokModel(true); // 实体类使用Lombok注解
        strategyConfig.setLogicDeleteFieldName("deleted"); // 设置逻辑删除字段名
        strategyConfig.setVersionFieldName("version"); // 设置乐观锁字段名
        generator.setStrategy(strategyConfig);

        /**
         * 执行生成操作
         */
        generator.execute();

    }
}

至此,MyBatis-Plus快速入门结束。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。