超级详细的MyBatis-Plus&SpringBoot整合MP


MyBatis-Plus

简介

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

SpringBoot整合MP

快速搭建MP

导入依赖

在springboot项目中如果导入了mybatisplus相关依赖,那么maven中mybatis就不会在生效了

<dependency>
  <groupId>com.baomidou</groupId>
  <!--下面坐标根据自己使用的SpringBoot版本二选一-->
  <!--SpringBoot2使用此版本-->
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <!--3.5.4开始,支持SpringBoot3使用此版本-->
  <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
  <version>最新版本</version>
</dependency>

创建数据连接

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/db19
      username: root
      password: 123456

编写Mapper文件

package com.ry.sofewin.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ry.sofewin.entity.Student;
import org.apache.ibatis.annotations.Mapper;

public interface StudentMapper extends BaseMapper<Student> {
}

运行

 @Autowired
    StudentMapper studentMapper;
    @Test
    void getAllStudents(){

        List<Student> students = studentMapper.selectList(null);
        System.out.println(students);
    }

CRUD操作

insert

 @Test
    void add() {
        Student student = new Student();
        student.setStuNo("10003");
        student.setStuName("wangwu");
        student.setGender(0);
        student.setAddress("太原市娄烦县");
        int insert = studentMapper.insert(student);
        System.out.println(insert);
    }

delete

@Test
public void del() {
    
  根据id删除信息
  int count = studentMapper.deleteById(1);
        System.out.println(count);
//批量删除
        ArrayList lists=new ArrayList();
        lists.add(2);
        lists.add(3);
        int count = studentMapper.deleteBatchIds(lists);
        System.out.println(count);*/
            HashMap map=new HashMap();
        map.put("gender","1");
        map.put("address","娄烦");
        int count = studentMapper.deleteByMap(map);
        System.out.println(count);*/
}

update

    @Test
    void add() {
        Student student = new Student();
        student.setStuNo("10003");
        student.setStuName("wangwu");
        student.setGender(0);
        student.setAddress("太原市娄烦县");
        int insert = studentMapper.insert(student);
        System.out.println(insert);
    }

select

@Test
    void selByWrapper(){
        QueryWrapper<Student> wrapper=new QueryWrapper();
        wrapper.like("address","小");
        List<Student> students = studentMapper.selectList(wrapper);
        System.out.println(students);
    }

持久层接口 Service Interface

介绍

IService是MP提供的一个通用的Service层接口,它封装了常见的CRUD操作,包括插入、删除、查询、分页等。通过继承IService接口,可以快速实现对数据库的基本操作,同时保持代码的简洁性可维护性

快速使用

service接口

public interface UserService extends IService<User> {
}

service实现类

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

:这里的BaseMapper可以换成UserMapper,因为你的mapper层的接口会继承BaseMapper

运行

@Test
    public void testSave(){
        //新增
        User user = new User();
        user.setName("赵六");
        user.setAge(26);
        user.setSex(1);
        user.setPassword("123777");
        user.setUserName("zhaoliu");
        boolean result = userService.save(user);
        System.out.println(result);
    }

    @Test
    public void testSaveOrUpdate(){
        //新增或修改(数据库表中没有这个便新增)
        User user = new User();
        user.setId(11L);
        user.setName("赵六1");
        user.setAge(26);
        user.setSex(1);
        user.setPassword("123777");
        user.setUserName("zhaoliu1");
        boolean result = userService.saveOrUpdate(user);
        System.out.println(result);
    }

    @Test
    public void testList(){
        //查询所有
        List<User> userList = userService.list();
        userList.forEach(s -> System.out.println(s));
    }

    @Test
    public void testGet(){
        //查询单个
        Optional<User> user  =  userService.getOptById(11L);
        System.out.println(user);
    }

    @Test
    public void testUpdate(){
        //修改
        User user = new User();
        user.setId(11L);
        user.setName("赵六2");
        user.setAge(26);
        user.setSex(1);
        user.setPassword("123888");
        user.setUserName("zhaoliu22");
        boolean result = userService.updateById(user);
        System.out.println(result);
    }

    @Test
    public void testDelete(){
        //根据id进行删除
        boolean result = userService.removeBatchByIds(Arrays.asList(11, 1813457884667904001L));
        System.out.println(result);
    }

    @Test
    public void testUpdateBatch(){
        //批量更新
        List<User> userList = new ArrayList<>();
        userList.add(new User(4L,"zhangwei1","123"));
        userList.add(new User(5L,"zhangwei2","1231"));
        boolean result = userService.updateBatchById(userList, userList.size());
        System.out.println(result);
    }

条件构造器

介绍

MP 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率减少 SQL 注入的风险
在MP中,Wrapper 类是构建查询和更新条件的核心工具

  • AbstractWrapper:是一个抽象类,提供了所有Wrapper类共有的方法和熟悉。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。
  • QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 andor 逻辑。
  • UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
  • LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下
  • LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。

使用

它可以和UserMapper或者UserService搭配一起使用,提高效率,常见的有eq、gt、ge、lt、le、between、like、isNull、in、insql、exists、apply

 @Test
    public void test1() {
        QueryWrapper qw = new QueryWrapper();
        qw.in("id", 1, 3, 4, 5, 6);
        List list = userService.list(qw);
        list.forEach(System.out::println);

    }

 @Test
    public void test7() {
        QueryWrapper qw = new QueryWrapper();
        qw.inSql("sex", "select sex from tb_user where age < 100 and name = '张三'");
        List list = userService.list(qw);
        list.forEach(System.out::println);

 }
 @Test
    public void test10() {
        QueryWrapper qw = new QueryWrapper();
        qw.eq("age", 21);
        qw.eq("sex", 0);
        qw.isNotNull("name");
        qw.apply("date_format(dateColumn, '%Y-%m-%d') = {0}", "2008-08-08");
        List list = userService.list(qw);
        list.forEach(System.out::println);

    }

使用配置

在 Spring Boot 项目中,可以通过 application.yml 或 application.properties 文件来配置 MyBatis-Plus。

mybatis-plus:
  configuration:
    # MyBatis 配置
    map-underscore-to-camel-case: true
    cache-enabled: false  # 是否开启二级缓存
  mapper-locations: classpath:/mapper/**.xml
  type-aliases-package: com.your.domain

常用注解配置

@TableName

该注解用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,可以使用这个注解来明确指定表名。

@TableId

该注解用于标记实体类中的主键字段。如果你的主键字段名为 id,你可以省略这个注解

  • value来指定数据库表的主键字段名,如果主键字段名不为id,可以用value来指定
  • type指定主键的生成策略,有5种枚举类型
    • IdType.AUTO:使用数据库自增 ID 作为主键。如果数据库表中主键没有设置自增,这种策略写上相当于0
    • IdType.NONE:无特定生成策略,如果全局配置中有 IdType 相关的配置,则会跟随全局配置。
    • IdType.INPUT:在插入数据前,由用户自行设置主键值。
    • IdType.ASSIGN_ID:自动分配 ID,适用于 LongIntegerString 类型的主键。默认使用雪花算法通过 IdentifierGeneratornextId 实现。
    • IdType.ASSIGN_UUID:自动分配 UUID,适用于 String 类型的主键。默认实现为 IdentifierGeneratornextUUID 方法。

@TableField

该注解用于标记实体类中的非主键字段,它告诉MP如何映射实体类字段到数据库表字段。如果你的实体类字段名遵循驼峰命名规则,并且与数据库表字段名一致,你可以省略这个注解。

@Version

该注解用于标记实体类中的字段作为乐观锁版本号字段
乐观锁是一种并发控制机制,它假设多个事务可以同时进行而不会互相干扰,只在提交事务时检查是否有冲突。通过在实体类中使用@Version注解,MyBatis-Plus 会在更新操作时自动检查版本号,确保在更新过程中数据没有被其他事务修改。

@TableLogic

该注解用于标记实体类中的字段作为逻辑删除字段逻辑删除是一种数据管理策略,它不是真正地从数据库中删除记录,而是在记录中标记该记录为已删除状态。通过使用@TableLogic注解,MyBatis-Plus 可以在查询、更新和删除操作中自动处理逻辑删除字段的值。

@TableLogic(value = "0", delval = "1") // 逻辑删除字段
    private Integer deleted;

deleted字段被标记为逻辑删除字段。@TableLogic注解的value属性指定了逻辑未删除的值(在这个例子中是0),而delval属性指定了逻辑删除的值(在这个例子中是1)。

  • 当执行查询操作时,MyBatis-Plus 会自动过滤掉标记为逻辑删除的记录,只返回未删除的记录。
  • 在执行更新操作时,如果更新操作会导致逻辑删除字段的值变为逻辑删除值,MyBatis-Plus 会自动将该记录标记为已删除。
  • 在执行删除操作时,MyBatis-Plus 会自动将逻辑删除字段的值更新为逻辑删除值,而不是物理删除记录。

数据库主键不采用自增策略,mybatis和mybatisplus怎么来进行实现

//1.新增数据时候,查询最后一条新增记录的id是多少,然后+1
//2.mybatis自动生成
//    <insert id="insertCategory" keyColumn="id" useGeneratedKeys="true">
//        insert into category values(#{pid},#{name},#{remark},#{status})
//    </insert>
//3.使用mybatisplus的自定义id生成器
//4.商业场景下的ID策略,redis序列号生成器,采用redis常用方法的incrment()方法

插件主体

分页插件

:版本要求:3.4.0 版本以上,如果版本低于3.4,就不能使用MybatisPlusInterceptor,而是直接使用各自的类
3.4版本分页配置

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType
        return interceptor;
    }
}

3.4版本以下配置

@Configuration
@MapperScan("com.ry.sofewin.mapper")
public class MybatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor paginationInterceptor=new PaginationInterceptor();
        paginationInterceptor.setDbType(DbType.MYSQL);
        return paginationInterceptor;
    }

代码运行

@Test
    public void testPage(){

        Page<Book> page = new Page<>(1,10);
        List<Book> bookList = bookService.list(page);
        page.setRecords(bookList);
        System.out.println(page.getTotal());
        System.out.println(page.getRecords());
    }

乐观锁插件

介绍:乐观锁是一种并发控制机制,用于确保在更新记录时,该记录未被其他事务修改。
实现原理

  1. 读取记录时,获取当前的版本号(version)。
  2. 在更新记录时,将这个版本号一同传递。
  3. 执行更新操作时,设置 version = newVersion 的条件为 version = oldVersion
  4. 如果版本号不匹配,则更新失败。

配置

@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

在实体类上加上**@Version注解**

public class YourEntity {
    @Version
    private Integer version;
    // 其他字段...
}

代码生成器

添加依赖

 <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--mybatis-plus代码生成器插件-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--代码生成器模板引擎依赖-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

代码书写

public class MybatisPlusGeneration {
    /**
     * 根据表名生成相应结构代码
     * @param databaseName 数据库名
     * @param tableName 表名
     */
    public static void Generation(String databaseName,String userName,String password,String... tableName){
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/"+databaseName+"?&useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai",userName,password)
                .globalConfig(builder -> {
                    builder.author("软赢科技")
                            //启用swagger
                            //.enableSwagger()
                            //指定输出目录
                            .outputDir(System.getProperty("user.dir")+"/src/main/java");
                })
                .packageConfig(builder -> {
                    builder.entity("entity")//实体类包名
                            .parent("com.ry.springbootmybatisplus2403")//父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
                            .controller("controller")//控制层包名
                            .mapper("mapper")//mapper层包名
                            //.other("dto")//生成dto目录 可不用
                            .service("service")//service层包名
                            .serviceImpl("service.impl")//service实现类包名
                            //自定义mapper.xml文件输出目录
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml,System.getProperty("user.dir")+"/src/main/resources/mapper"));
                })
                .strategyConfig(builder -> {
                    //设置要生成的表名
                    builder.addInclude(tableName)
                            //.addTablePrefix("sys_")//设置表前缀过滤
                            .entityBuilder()
                            .enableLombok()
                            .enableChainModel()
                            .naming(NamingStrategy.underline_to_camel)//数据表映射实体命名策略:默认下划线转驼峰underline_to_camel
                            .columnNaming(NamingStrategy.underline_to_camel)//表字段映射实体属性命名规则:默认null,不指定按照naming执行
                            .idType(IdType.AUTO)//添加全局主键类型
                            .formatFileName("%s")//格式化实体名称,%s取消首字母I,
                            .mapperBuilder()
                            .enableMapperAnnotation()//开启mapper注解
                            .enableBaseResultMap()//启用xml文件中的BaseResultMap 生成
                            .enableBaseColumnList()//启用xml文件中的BaseColumnList
                            .formatMapperFileName("%sMapper")//格式化Dao类名称
                            .formatXmlFileName("%sMapper")//格式化xml文件名称
                            .serviceBuilder()
                            .formatServiceFileName("%sService")//格式化 service 接口文件名称
                            .formatServiceImplFileName("%sServiceImpl")//格式化 service 接口文件名称
                            .controllerBuilder()
                            .enableRestStyle();
                })
//                .injectionConfig(consumer -> {
//            Map<String, String> customFile = new HashMap<>();
//            // 配置DTO(需要的话)但是需要有能配置Dto的模板引擎,比如freemarker,但是这里我们用的VelocityEngine,因此不多作介绍
//            customFile.put("DTO.java", "/templates/entityDTO.java.ftl");
//            consumer.customFile(customFile);
//           })
                .execute();
    }

    public static void main(String[] args) {
        System.out.println(System.getProperty("user.dir")+"/src/main/java");
        Generation("erpdb","root","root123456","measure","member");
    }
}

代码生成器加强版

使用mybatisx生成
image.png
image.png
image.png
需要自己生成实体类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@Zeal

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

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

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

打赏作者

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

抵扣说明:

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

余额充值