若依集成MybatisPlus

目录

一、依赖变更

1. MybatisPlus依赖

2. pagehelper依赖修改

二、相关配置

1. yml配置

1.1 注释掉原Mybatis配置

1.2 加入MybatisPlus的配置

1.3 注释掉原MybatisConfig.class

三、其他配置及功能实现

1. 自动补全create_time等信息

2. 实现MP分页

3. 实现MybatisPlus代码生成

3.1 方法一:使用MP自带的代码生成方法

3.2 方法二:修改若依框架的代码生成部分以实现MP代码生成


一、依赖变更

1. MybatisPlus依赖

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

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.5.2</version>
    <scope>compile</scope>
</dependency>

建议使用3.5.1及以上版本,3.4.x版分页有问题

2. pagehelper依赖修改

pagehelper依赖中不引用Mybatis相关依赖(MP依赖中自带Mybatis依赖),这样pagehelper分页依然可用

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>mybatis-spring</artifactId>
            <groupId>org.mybatis</groupId>
        </exclusion>
        <exclusion>
            <artifactId>mybatis</artifactId>
            <groupId>org.mybatis</groupId>
        </exclusion>
    </exclusions>
</dependency>

二、相关配置

1. yml配置

1.1 注释掉原Mybatis配置

# MyBatis配置
#mybatis:
#    # 搜索指定包别名
#    typeAliasesPackage: com.bsd.**.domain
#    # 配置mapper的扫描,找到所有的mapper.xml映射文件
#    mapperLocations: classpath*:mapper/**/*Mapper.xml
#    # 加载全局的配置文件
#    configLocation: classpath:mybatis/mybatis-config.xml

1.2 加入MybatisPlus的配置

mybatis-plus:
  # Mapper.xml 文件位置 Maven 多模块项目的扫描路径需以 classpath*: 开头
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  #  #MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名 实体扫描,多个package用逗号或者分号分隔
  type-aliases-package: com.bsd.**.domain
#  config-location: classpath:mybatis/mybatis-config.xml
  #  #通过父类(或实现接口)的方式来限定扫描实体
  #  typeAliasesSuperType: com.vanhr.user.dao.entity.baseEntity
  #  #枚举类 扫描路径 如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性
  #  typeEnumsPackage: com.vanhr.user.dao.enums
  # 启动时是否检查 MyBatis XML 文件的存在,默认不检查 仅限spring boot 使用
  checkConfigLocation : true
  #  #通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种:
  #  # ExecutorType.SIMPLE:该执行器类型不做特殊的事情,为每个语句的执行创建一个新的预处理语句(PreparedStatement)
  #  # ExecutorType.REUSE:该执行器类型会复用预处理语句(PreparedStatement)
  #  # ExecutorType.BATCH:该执行器类型会批量执行所有的更新语句
  #  executorType: SIMPLE
  #  # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
  #  configurationProperties:
  configuration: # MyBatis 原生支持的配置
    # 是否开启自动驼峰命名规则(camel case)映射
    map-underscore-to-camel-case: true
    # 枚举处理类,如果配置了该属性,枚举将统一使用指定处理器进行处理
    #   org.apache.ibatis.type.EnumTypeHandler : 存储枚举的名称
    #   org.apache.ibatis.type.EnumOrdinalTypeHandler : 存储枚举的索引
    #   com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler : 枚举类需要实现IEnum接口或字段标记@EnumValue注解.(3.1.2以下版本为EnumTypeHandler)
    #    defaultEnumTypeHandler: com.baomidou.mybatisplus.extension.handlers.MybatisEnumTypeHandler
    # 配置JdbcTypeForNull, oracle数据库必须配置
    jdbc-type-for-null: null
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
  #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config: # 全局策略配置
    # 是否控制台 print mybatis-plus 的 LOGO
    banner: true
    db-config:
      # id类型
      id-type: auto
      # 表名是否使用下划线命名,默认数据库表使用下划线命名
      table-underline: true
      #是否开启大写命名,默认不开启
#      capital-mode: false
#      #逻辑已删除值,(逻辑删除下有效) 需要注入逻辑策略LogicSqlInjector 以@Bean方式注入
#      logic-not-delete-value: 0
#      #逻辑未删除值,(逻辑删除下有效)
#      logic-delete-value: 1

1.3 注释掉原MybatisConfig.class

位置:com/bsd/framework/config/MyBatisConfig.java

建议先别删除,若出现问题还可以退回去使用Mybatis

此时MybatisPlus已经可以正常使用了,下面再记录一下其他常用配置

三、其他配置及功能实现

1. 自动补全create_time等信息

配置一个组件类,实现MP的MetaObjectHandler类,重写里面的方法即可

package com.bsd.framework.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.bsd.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {


    @Override
    public void insertFill(MetaObject metaObject) {
        String operator = null;
        try {
            operator = SecurityUtils.getUsername();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        this.setFieldValByName("createBy", operator, metaObject);
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateBy", operator, metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        String operator = null;
        try {
            operator = SecurityUtils.getUsername();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        this.setFieldValByName("updateBy", operator, metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
 

2. 实现MP分页

 创建一个MyBatisPlusConfig类,将MP的拦截器交由Spring管理

package com.bsd.framework.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {

    /**
     * 分页插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

3. 实现MybatisPlus代码生成

3.1 方法一:使用MP自带的代码生成方法

3.1.1 引入MP代码生成依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>

因为MP代码生成需要连接数据库,所以还要引入数据库连接依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

3.1.2 使用MP的方法生成代码

创建MPCodeGenerator类,在generation方法中进行相关配置,再在main方法中调用generation方法,传入相关参数后执行main方法实现生成代码

package com.bsd.generator.util;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.bsd.common.core.domain.BaseEntity;
import com.bsd.common.utils.StringUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class MPCodeGenerator {

    public static void main(String[] args) {
        String filePath = System.getProperty("user.dir") + "/src/main/java";
        generation("ljf", filePath,"d_test", "d_record_annex");
    }

    /**
     * 根据表名生成相应结构代码
     *
     * @param author 作者名
     * @param tableName  表名
     */
    public static void generation(String author, String filePath, String... tableName) {
        FastAutoGenerator.create("jdbc:mysql://xxxxxxx:3306/safety?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8",
                "XXXX", "XXXXX")
                .globalConfig(builder -> {
                    builder.author(author)
                            //启用swagger
                            .enableSwagger()
                            .dateType(DateType.TIME_PACK)
                            //指定输出目录
                            .outputDir(filePath);
                })
                .packageConfig(builder -> {
                    builder.entity("domain")//实体类包名
                            .parent("com.bsd.device")//父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
                            .controller("controller")//控制层包名
                            .mapper("mapper")//mapper层包名
                            //.other("dto")//生成dto目录 可不用
                            .service("service")//service层包名
                            .serviceImpl("service.impl")//service实现类包名
                            //自定义mapper.xml文件输出目录
                            .pathInfo(Collections.singletonMap(OutputFile.xml, filePath + "/resources/mapper/device"));
                })
                .strategyConfig(builder -> {
                    //设置要生成的表名
                    builder.addInclude(tableName)
                            .addTablePrefix("d_")//设置表前缀过滤
                            .entityBuilder()
                            .enableLombok()
                            .enableChainModel()
                            .superClass(BaseEntity.class)//设置父类
                            .enableTableFieldAnnotation()//开启生成实体时生成字段注解
                            .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();
    }
}

3.2 方法二:修改若依框架的代码生成部分以实现MP代码生成

因为若依的代码生成是使用velocity确定模版,再根据模版来生成代码,所以只要将MP相关代码部分(主要是一些注解和继承接口)添加到velocity模版即可。

Velocity语法教学:Java Velocity模板引擎详解

下面将修改好的vm文件贴出(包括domain、mapper、service、serviceImpl):

domain.java.vm

package ${packageName}.domain;

#foreach ($import in $importList)
import ${import};
#end
import com.bsd.common.annotation.Excel;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.TableId;
#if($table.crud || $table.sub)
import com.bsd.common.core.domain.BaseEntity;
#elseif($table.tree)
import com.bsd.common.core.domain.TreeEntity;
#end

/**
 * ${functionName}对象 ${tableName}
 *
 * @author ${author}
 * @date ${datetime}
 */
#if($table.crud || $table.sub)
    #set($Entity="BaseEntity")
#elseif($table.tree)
    #set($Entity="TreeEntity")
#end
@Data
@TableName("${tableName}")
public class ${ClassName} extends ${Entity} {

    private static final long serialVersionUID=1L;

#foreach ($column in $columns)
#if(!$table.isSuperColumn($column.javaField))
    /** $column.columnComment */
#if($column.list)
#set($parentheseIndex=$column.columnComment.indexOf("("))
#if($parentheseIndex != -1)
#set($comment=$column.columnComment.substring(0, $parentheseIndex))
#else
#set($comment=$column.columnComment)
#end
#if($parentheseIndex != -1)
    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
#elseif($column.javaType == 'Date')
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
#else
    @Excel(name = "${comment}")
#end
#end
#if($column.javaField == 'id')
    @TableId(type = IdType.AUTO)
#end
    private $column.javaType $column.javaField;

#end
#end
#if($table.sub)
    /** $table.subTable.functionName信息 */
    private List<${subClassName}> ${subclassName}List;
#end
}

mapper.java.vm

package ${packageName}.mapper;

import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${packageName}.domain.${ClassName};
#if($table.sub)
import ${packageName}.domain.${subClassName};
#end

/**
 * ${functionName}Mapper接口
 *
 * @author ${author}
 * @date ${datetime}
 */
public interface ${ClassName}Mapper extends BaseMapper<${ClassName}>
{
    /**
     * 查询${functionName}
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return ${functionName}
     */
    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});

    /**
     * 查询${functionName}列表
     *
     * @param ${className} ${functionName}
     * @return ${functionName}集合
     */
    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});

    /**
     * 新增${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
    public int insert${ClassName}(${ClassName} ${className});

    /**
     * 修改${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
    public int update${ClassName}(${ClassName} ${className});

    /**
     * 删除${functionName}
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return 结果
     */
    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});

    /**
     * 批量删除${functionName}
     *
     * @param ${pkColumn.javaField}s 需要删除的数据主键集合
     * @return 结果
     */
    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
#if($table.sub)

    /**
     * 批量删除${subTable.functionName}
     *
     * @param ${pkColumn.javaField}s 需要删除的数据主键集合
     * @return 结果
     */
    public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);

    /**
     * 批量新增${subTable.functionName}
     *
     * @param ${subclassName}List ${subTable.functionName}列表
     * @return 结果
     */
    public int batch${subClassName}(List<${subClassName}> ${subclassName}List);


    /**
     * 通过${functionName}主键删除${subTable.functionName}信息
     *
     * @param ${pkColumn.javaField} ${functionName}ID
     * @return 结果
     */
    public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
#end
}

service.java.vm

package ${packageName}.service;

import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import ${packageName}.domain.${ClassName};

/**
 * ${functionName}Service接口
 *
 * @author ${author}
 * @date ${datetime}
 */
public interface I${ClassName}Service extends IService<${ClassName}>
{
    /**
     * 查询${functionName}
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return ${functionName}
     */
    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});

    /**
     * 查询${functionName}列表
     *
     * @param ${className} ${functionName}
     * @return ${functionName}集合
     */
    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});

    /**
     * 新增${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
    public int insert${ClassName}(${ClassName} ${className});

    /**
     * 修改${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
    public int update${ClassName}(${ClassName} ${className});

    /**
     * 批量删除${functionName}
     *
     * @param ${pkColumn.javaField}s 需要删除的${functionName}主键集合
     * @return 结果
     */
    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);

    /**
     * 删除${functionName}信息
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return 结果
     */
    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
}

serviceImpl.java.vm

package ${packageName}.service.impl;

import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
#foreach ($column in $columns)
#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
import com.bsd.common.utils.DateUtils;
#break
#end
#end
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#if($table.sub)
import java.util.ArrayList;
import com.bsd.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import ${packageName}.domain.${subClassName};
#end
import ${packageName}.mapper.${ClassName}Mapper;
import ${packageName}.domain.${ClassName};
import ${packageName}.service.I${ClassName}Service;

/**
 * ${functionName}Service业务层处理
 *
 * @author ${author}
 * @date ${datetime}
 */
@Service
public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}> implements I${ClassName}Service
{
    @Autowired
    private ${ClassName}Mapper ${className}Mapper;

    /**
     * 查询${functionName}
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return ${functionName}
     */
    @Override
    public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
    {
        return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
    }

    /**
     * 查询${functionName}列表
     *
     * @param ${className} ${functionName}
     * @return ${functionName}
     */
    @Override
    public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
    {
        return ${className}Mapper.select${ClassName}List(${className});
    }

    /**
     * 新增${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
#if($table.sub)
    @Transactional
#end
    @Override
    public int insert${ClassName}(${ClassName} ${className})
    {
#foreach ($column in $columns)
#if($column.javaField == 'createTime')
        ${className}.setCreateTime(DateUtils.getNowDate());
#end
#end
#if($table.sub)
        int rows = ${className}Mapper.insert${ClassName}(${className});
        insert${subClassName}(${className});
        return rows;
#else
        return ${className}Mapper.insert${ClassName}(${className});
#end
    }

    /**
     * 修改${functionName}
     *
     * @param ${className} ${functionName}
     * @return 结果
     */
#if($table.sub)
    @Transactional
#end
    @Override
    public int update${ClassName}(${ClassName} ${className})
    {
#foreach ($column in $columns)
#if($column.javaField == 'updateTime')
        ${className}.setUpdateTime(DateUtils.getNowDate());
#end
#end
#if($table.sub)
        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}());
        insert${subClassName}(${className});
#end
        return ${className}Mapper.update${ClassName}(${className});
    }

    /**
     * 批量删除${functionName}
     *
     * @param ${pkColumn.javaField}s 需要删除的${functionName}主键
     * @return 结果
     */
#if($table.sub)
    @Transactional
#end
    @Override
    public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s)
    {
#if($table.sub)
        ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
#end
        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s);
    }

    /**
     * 删除${functionName}信息
     *
     * @param ${pkColumn.javaField} ${functionName}主键
     * @return 结果
     */
#if($table.sub)
    @Transactional
#end
    @Override
    public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
    {
#if($table.sub)
        ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
#end
        return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
    }
#if($table.sub)

    /**
     * 新增${subTable.functionName}信息
     *
     * @param ${className} ${functionName}对象
     */
    public void insert${subClassName}(${ClassName} ${className})
    {
        List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
        ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
        if (StringUtils.isNotNull(${subclassName}List))
        {
            List<${subClassName}> list = new ArrayList<${subClassName}>();
            for (${subClassName} ${subclassName} : ${subclassName}List)
            {
                ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
                list.add(${subclassName});
            }
            if (list.size() > 0)
            {
                ${className}Mapper.batch${subClassName}(list);
            }
        }
    }
#end
}

有关MybatisPlus的其他问题,或者上面未说明的问题,均可查看MybatisPlus官网指南:简介 | MyBatis-Plus

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值