【Spring Boot后端组件】mybatis-plus使用

06-02 1519阅读

文章目录

  • mybatis-plus使用
    • 一、依赖引入
    • 二、添加相关配置项
    • 三、功能详解
      • 1.自增主键
      • 2.逻辑删除
      • 3.操作时间自动填充
      • 4.其他字段自动填充
      • 5.分页查询
      • 6.自定义动态查询
      • 7.代码生成器
      • 8.代码生成器(自定义模板)

        mybatis-plus使用

        一、依赖引入

        pom.xml文件

        
            4.0.0
            
                org.springframework.boot
                >spring-boot-starter-parent
                2.7.4
                
            
            >mybatis-plus-demo
            
                
                
                    org.springframework.boot
                    spring-boot-starter-jdbc
                
                 
                    mysql
                    mysql-connector-java
                    5.1.48
                
                
                
                    com.baomidou
                    mybatis-plus-boot-starter
                    3.2.0
                
                
                    org.springframework.boot
                    spring-boot-starter-web
                
                
                    org.projectlombok
                    lombok
                
            
        
        

        二、添加相关配置项

        application.yaml

        spring:
          # datasource 数据源配置内容
          datasource:
            url: jdbc:mysql://127.0.0.1:3306/test-user?useSSL=false&useUnicode=true&characterEncoding=UTF-8
            driver-class-name: com.mysql.jdbc.Driver
            username: root
            password: root1234
        

        三、功能详解

        1.自增主键

        CREATE TABLE auto_increment (
            id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
            name VARCHAR(100) NOT NULL COMMENT '名称',
            create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
        ) COMMENT='主键自增表';
        

        表单说明:在数据库软件如navicat中直接插入数据时,数据呈现主键自增情况,但使用mybatis-plus直接插入数据则不会。

        (1)直接为实体id字段添加注解@TableId(type = IdType.AUTO),加上此注解后插入的数据就可以实现主键自增了。

        实体类如下:

        @TableName(value = "auto_increment")
        @Data
        public class AutoIncrementDO {
            @TableId(type = IdType.AUTO)
            private Long id;
            private String name;
            private LocalDateTime createTime;
        }
        

        (2)全局配置,在配置文件中加入以下配置

        mybatis-plus:
          global-config:
            db-config:
              id-type: auto # 全局主键策略
        

        实体类如下:

        @TableName(value = "auto_increment")
        @Data
        public class AutoIncrementDO {
            // 字段名id时会自动识别为主键,否则需要加上 @TableId 注解
            private Long id;
            private String name;
            private LocalDateTime createTime;
        }
        

        ps:数据库主键必须设置为自增,否则会报错

        2.逻辑删除

        CREATE TABLE logic_delete (
            id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
        		name VARCHAR(50) NOT NULL COMMENT '名称',
            create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
            update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
            deleted BIT NOT NULL DEFAULT FALSE COMMENT '是否删除'
        ) COMMENT='逻辑删除表';
        

        表单说明:deleted字段默认设为false即0,删除数据时值需要将deleted字段置为1即可,不需要真正的删除数据。

        mybatis-plus如何实现这一需求呢?

        (1)直接在表示逻辑删除的字段上添加注解@TableLogic即可,默认值为0,删除值为1,若想反过来需要自定义@TableLogic(value = "1", delval = "0")或者@TableLogic(value = "false", delval = "true")

        (2)全局配置:表示删除的字段上添加注解@TableLogic,全局配置默认值和删除值,配置如下。

        mybatis-plus:
          global-config:
            db-config:
              logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
              logic-delete-value: 1 # 逻辑已删除值(默认为 1)
        

        ps:若字段上的注解不仅仅为@TableLogic,而是例如@TableLogic(value = "1", delval = "0")等情况,那么该表的逻辑删除按该注解来,即该表0表示删除

        3.操作时间自动填充

        CREATE TABLE auto_update_time (
            id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键',
            content VARCHAR(255) NOT NULL COMMENT '名称',
            create_time TIMESTAMP DEFAULT NULL COMMENT '创建时间',
            update_time TIMESTAMP DEFAULT NULL COMMENT '更新时间'
        )COMMENT='时间自动更新表';
        

        表单说明:为不产生影响,数据库中创建时间与更新时间不设置默认值,也不自动更新。

        mybatis-plus实现操作时间自动填充以及更新步骤如下:

        【Spring Boot后端组件】mybatis-plus使用
        (图片来源网络,侵删)

        ①字段上添加如下注解:

        @Data
        @TableName("auto_update_time")
        public class AutoUpdateTimeDO {
            @TableId(type = IdType.AUTO)
            private Long id;
            private String content;
            @TableField(fill = FieldFill.INSERT)
            private LocalDateTime createTime;
            @TableField(fill = FieldFill.INSERT_UPDATE)
            private LocalDateTime updateTime;
        }
        

        ②实现 MetaObjectHandler 接口:

        【Spring Boot后端组件】mybatis-plus使用
        (图片来源网络,侵删)
        @Component
        public class DefaultDBFieldHandler implements MetaObjectHandler {
            @Override
            public void insertFill(MetaObject metaObject) {
                setInsertFieldValByName("createTime", LocalDateTime.now(), metaObject);
                setInsertFieldValByName("updateTime", LocalDateTime.now(), metaObject);
            }
            @Override
            public void updateFill(MetaObject metaObject) {
                setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
            }
        }
        

        4.其他字段自动填充

        如创建人与更新人自动填充,这里会和创建时间以及更新时间自动填充一起,二者实现都需要实现MetaObjectHandler接口。

        实现如下:

        ①字段上添加如下注解:

        @Data
        @TableName(value = "auto_fill_operator")
        public class AutoFillOperatorDO extends BaseDO{
            @TableId(type = IdType.AUTO)
            private Long id;
            private String content;
        }
        
        @Data
        public class BaseDO {
            @TableField(fill = FieldFill.INSERT)
            private String creator;
            @TableField(fill = FieldFill.INSERT_UPDATE)
            private String updater;
            @TableField(fill = FieldFill.INSERT)
            private LocalDateTime createTime;
            @TableField(fill = FieldFill.INSERT_UPDATE)
            private LocalDateTime updateTime;
        }
        

        ②实现 MetaObjectHandler 接口:

        @Component
        public class DefaultDBFieldHandler implements MetaObjectHandler {
            @Override
            public void insertFill(MetaObject metaObject) {
                if (metaObject.getOriginalObject() instanceof BaseDO) {
                    BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
                    LocalDateTime current = LocalDateTime.now();
                    // 创建时间为空,则填充当前时间
                    if (Objects.isNull(baseDO.getCreateTime())) {
                        baseDO.setCreateTime(current);
                    }
                    // 更新时间为空,则填充当前时间
                    if (Objects.isNull(baseDO.getUpdateTime())) {
                        baseDO.setUpdateTime(current);
                    }
                    String user = "creator";
                    // 创建人为空,则填充当前用户
                    if (Objects.isNull(baseDO.getCreator())) {
                        baseDO.setCreator(user);
                    }
                    // 更新人为空,则填充当前用户
                    if (Objects.isNull(baseDO.getUpdater())) {
                        baseDO.setUpdater(user);
                    }
                }
            }
            @Override
            public void updateFill(MetaObject metaObject) {
                // 更新时间为空,则以当前时间为更新时间
                Object modifyTime = getFieldValByName("updateTime", metaObject);
                if (Objects.isNull(modifyTime)) {
                    setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
                }
                // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
                Object modifier = getFieldValByName("updater", metaObject);
                String user = "updater";
                if (Objects.isNull(modifier)) {
                    setFieldValByName("updater", user, metaObject);
                }
            }
        }
        

        5.分页查询

        @Mapper
        public interface CrudBaseMaoper extends BaseMapper {
        }
        
        @Service
        public class CrudBaseServiceImpl {
            @Resource
            private CrudBaseMaoper crudBaseMaoper;
            public IPage page(String name) {
                // 构造分页参数
                Page page = new Page(1, 10); // 当前页, 每页显示条数
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.lambda().like(CrudBaseDO::getCompanyName, name);
                return crudBaseMaoper.selectPage(page, queryWrapper);
            }
        

        分页查询total为0,需要配置分页插件,如下:

        @Configuration
        public class MybatisPlusConfig {
            // 分页查询拦截器,可以获取total值
            @Bean
            public MybatisPlusInterceptor mybatisPlusInterceptor() {
                MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
                interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 根据数据库类型选择
                return interceptor;
            }
        }
        

        6.自定义动态查询

        场景:在数据库查询中,经常遇到需要根据多个可选字段进行动态查询的情况。传统写法需要为每个字段编写判空逻辑,代码冗长且重复。

        通过自定义 LambdaQueryWrapper 扩展方法,实现简洁的动态查询:

        示例:

        public class LambdaQueryWrapperX extends LambdaQueryWrapper {
            public LambdaQueryWrapperX likeIfPresent(SFunction column, String val) {
                if (StringUtils.hasText(val)) {
                    return (LambdaQueryWrapperX) super.like(column, val);
                }
                return this;
            }
        }
        
        @Mapper
        public interface CrudProMapper extends BaseMapper {
        }
        
        @Service
        public class CrudProServiceImpl implements CrudProService {
            @Resource
            private CrudProMapper crudProMapper;
            @Override
            public IPage getCrudProPage(CrudProPageReqVO reqVO) {
                IPage page = new Page(1, 10);
                return crudProMapper.selectPage(page, new LambdaQueryWrapperX()
                        .likeIfPresent(CrudProDO::getCompanyName, reqVO.getCompanyName())
                        .likeIfPresent(CrudProDO::getCompanyCode, reqVO.getCompanyCode())
                );
            }
        }
        

        其他方法也可以一样的实现,比如eqIfPresent

        7.代码生成器

        (1)相关依赖

         
                
                    com.baomidou
                    mybatis-plus-boot-starter
                    3.5.3.1
                
                
                
                
                    com.baomidou
                    mybatis-plus-generator
                    3.5.3.1
                
                
                
                    org.apache.velocity
                    velocity-engine-core
                    2.3
                
                
                    org.freemarker
                    freemarker
                
        

        (2)生成器代码

        import com.baomidou.mybatisplus.generator.FastAutoGenerator;
        import com.baomidou.mybatisplus.generator.config.OutputFile;
        import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
        import java.util.Collections;
        public class CodeGenerator {
            public static void main(String[] args) {
                // 多模块地址前缀,没有可不写
                String prefixPath = "/kaishu-sql-crud/kaishu-sql-crud-mybatis-plus-pro/";
                FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/test-user?useSSL=false&useUnicode=true&characterEncoding=UTF-8",
                                "root",
                                "root1234")
                        .globalConfig(builder -> {
                            builder.author("kaishu")       // 设置作者
                                    .outputDir(System.getProperty("user.dir") + prefixPath + "/src/main/java") // 输出目录
                                    .enableSwagger()        // 开启swagger
                                    .fileOverride();        // 覆盖已生成文件
                        })
                        .packageConfig(builder -> {
                            builder.parent("org.kaishu.sql.crud.mybatis.plus.pro")    // 设置父包名
                                    .moduleName("generatordemo")     // 设置父包模块名
                                    .pathInfo(Collections.singletonMap(OutputFile.xml,
                                            System.getProperty("user.dir") + prefixPath + "/src/main/resources/mapper")); // 设置mapperXml路径
                        })
                        .strategyConfig(builder -> {
                            builder.addInclude("t_auto_genarater", "t_test_auto_genarater") // 设置需要生成的表名
                                    .addTablePrefix("t_", "t_") // 设置过滤表前缀
                                    .entityBuilder()         // 实体类配置
                                    .enableLombok()         // 启用Lombok
                                    .controllerBuilder()    // Controller配置
                                    .enableRestStyle()      // 启用@RestController
                                    .mapperBuilder()        // Mapper配置
                                    .enableMapperAnnotation(); // 启用@Mapper
                        })
                        .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎
                        .execute();
            }
        }
        

        更详细的配置参考如下:

        (1)实体类生成配置

        .strategyConfig(builder -> {
            builder.entityBuilder()
                .enableLombok() // 使用Lombok
                .enableChainModel() // 链式模型
                .enableRemoveIsPrefix() // 移除is前缀
                .enableTableFieldAnnotation() // 字段注解
                .versionColumnName("version") // 乐观锁字段名
                .logicDeleteColumnName("deleted") // 逻辑删除字段名
                .naming(NamingStrategy.underline_to_camel) // 命名策略
                .columnNaming(NamingStrategy.underline_to_camel)
                .addSuperEntityColumns("id", "create_time", "update_time") // 公共字段
                .formatFileName("%sEntity") // 文件名称格式
                .addIgnoreColumns("is_deleted"); // 忽略字段
        })
        

        (2)Mapper生成配置

        .strategyConfig(builder -> {
            builder.mapperBuilder()
                .enableBaseResultMap() // 生成resultMap
                .enableBaseColumnList() // 生成columnList
                .enableMapperAnnotation() // @Mapper注解
                .formatMapperFileName("%sDao") // Mapper文件命名
                .formatXmlFileName("%sXml"); // Xml文件命名
        })
        

        (3)Service生成配置

        .strategyConfig(builder -> {
            builder.serviceBuilder()
                .formatServiceFileName("%sService") // Service接口命名
                .formatServiceImplFileName("%sServiceImpl"); // Service实现类命名
        })
        

        (4)Controller生成配置

        .strategyConfig(builder -> {
            builder.controllerBuilder()
                .enableRestStyle() // 使用@RestController
                .enableHyphenStyle() // 使用驼峰转连字符
                .formatFileName("%sController") // 文件命名
                .enableFileOverride(); // 覆盖已生成文件
        })
        

        8.代码生成器(自定义模板)

        示例:这里只自定义实体类生成模板,其余照旧,这里我需要让实体类都继承我已定义好的的类BaseDO

        (1)依赖同上

        (2)生成器代码,基本同上

        .strategyConfig(builder -> {
           ...
        })
        // 加上这行代码即可
        .templateConfig(builder -> {
                            builder.entity("/templates/custom-entity.java");
                        })
        

        (2)自定义实体模板文件,在\src\main\resources\templates\目录下新建custom-entity.java.ftl文件,文件内容如下

        package ${package.Entity};
        
        import com.baomidou.mybatisplus.annotation.TableName;
        import com.baomidou.mybatisplus.annotation.TableField;
        import lombok.Data;
        import lombok.EqualsAndHashCode;
        
        import org.kaishu.sql.crud.mybatis.plus.pro.dal.dataobject.BaseDO;
        
        /**
        * ${table.comment!} 实体类
        *
        * @author ${author}
        * @since ${date}
        */
        @Data
        @EqualsAndHashCode(callSuper = true)
        @TableName("${table.name}")
        public class ${entity} extends BaseDO {
        private static final long serialVersionUID = 1L;
        
        
            
                /**
                * ${field.comment!}
                */
                @TableField("${field.name}")
                private ${field.propertyType} ${field.propertyName};
            
        
        }
        

        ·

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码