SpringBoot整合mybatis-plus并实现代码自动生成 ,自定义数据库字段类型转换

 

1、引入maven

 (代码是连接mysql)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <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.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.20</version>
        </dependency>

 

DruidConfig.java

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.*;
import javax.sql.DataSource;
import java.io.IOException;

/**
 * druid数据源配置类
 */
@Configuration
public class DruidConfig {


/**
     * 去除监控页面底部的广告
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
    {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // 创建filter进行过滤
        Filter filter = new Filter()
        {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
            {
            }

            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException
            {
                chain.doFilter(request, response);
                // 重置缓冲区,响应头不会被重置
                response.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换banner, 除去底部的广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                response.getWriter().write(text);
            }

            @Override
            public void destroy()
            {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(commonJsPattern);
        return registrationBean;
    }
}

 

 MybatisPlusConfig.java   配置类(配置项根据自己的来)

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

/**
 * Mybatis Plus 配置
 *
 * @author 
 */
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor());
        // 乐观锁插件
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
        // 阻断插件
        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
        return interceptor;
    }

    /**
     * 分页插件,自动识别数据库类型 https://baomidou.com/pages/97710a/#paginationinnerinterceptor
     */
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 设置数据库类型为mysql
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        return paginationInnerInterceptor;
    }

    /**
     * 乐观锁插件 https://baomidou.com/pages/0d93c0/#optimisticlockerinnerinterceptor
     */
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
        return new OptimisticLockerInnerInterceptor();
    }

    /**
     * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/pages/c571bc/#blockattackinnerinterceptor
     */
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
        return new BlockAttackInnerInterceptor();
    }
}

 加了上面这个 BlockAttackInnerInterceptor  拦截器的话

如果进行全表操作会报错:Cause: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation

 

 

application.yml 增加

mybatis-plus:
  #扫描mapper文件所在位置
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  #可以指定实体类所在包路径
  typeAliasesPackage: com.rnce.model
  global-config:
    banner: false
    db-config:
      # 主键类型 0:数据库ID自增 1.未定义 2.用户输入 3 id_worker 4.uuid 5.id_worker字符串表示
      id-type: AUTO
      #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
      field-strategy: NOT_NULL
      # 默认数据库表下划线命名
      table-underline: true
#  configuration:
#    map-underscore-to-camel-case: false
#    cache-enabled: true #配置的缓存的全局开关
#    lazyLoadingEnabled: true #延时加载的开关
#    multipleResultSetsEnabled: true #开启的话,延时加载一个属性时会加载该对象全部属性,否则按需加载属性
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用

spring:
  #DATABASE CONFIG
  #autoconfigure:
    # exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  datasource:
    #driver-class-name: com.mysql.jdbc.Driver
    driverClassName: com.mysql.cj.jdbc.Driver
    username: dsk
    password: Hz56
    url: jdbc:mysql://106.103:3306/dwk?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=Asia/Shanghai
    type: com.alibaba.druid.pool.DruidDataSource   #这里是配置druid连接池,以下都是druid的配置信息
    druid:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      testWhileIdle: true
      validationQuery: SELECT 1 FROM DUAL
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username: admin
        login-password: 123
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true

 

 

如果需要批量操作

MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL

 

 

如果是postsql的话 依赖替换为

        <!-- postgresql依赖 -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.5</version>
        </dependency>

 

驱动改为

 driver-class-name: org.postgresql.Driver

 

 

 

 

启动器上增加 要把Mapper接口文件的包扫描进去

 

 

伪代码示例

entity

@Data
public class History implements Serializable {


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


    private String name;

 

 

mapper

@Mapper
public interface HistoryMapper extends BaseMapper<History> {

 

 

service

@Service
public class HistoryService extends ServiceImpl<HistoryMapper,History> implements IService<History> {
}

 

 

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

//交给spring管理
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {


    //使用mp实现添加操作,这个方法会执行,metaObject元数据(表中的名字,表中的字段)
    @Override
    public void insertFill(MetaObject metaObject) {
        //根据名称设置属性值
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);

    }
    //使用mp实现修改操作,这个方法会执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

 

字段增加

 @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

 

 

 除了用自带的方法,也可以自定义sql

参考:https://baomidou.com/pages/10c804/#%E4%BD%BF%E7%94%A8-wrapper-%E8%87%AA%E5%AE%9A%E4%B9%89sql

 

分页转换参考

protected ResultBodyPageVO successPageResp(IPage pageImpl) {
    ResultBodyPageVO.CommonPageResultVOBuilder builder = new ResultBodyPageVO.CommonPageResultVOBuilder();
    builder.success().data(pageImpl.getRecords()).totalSize(pageImpl.getTotal())
            .pageNumber((int) (pageImpl.getCurrent())).totalPages((int) pageImpl.getPages())
            .pageSize((int) pageImpl.getSize());
    return builder.build();
}
import com.test.framework.rsps.ResultBody;
import com.test.framework.rsps.ResultStatus;
import lombok.Data;

@Data
public class ResultBodyPageVO<T> extends ResultBody<T> {

    /**
     * 当前页面
     */
    private long pageNumber;// 当前页


    /**
     * 当前页尺寸
     */
    private long pageSize;

    /**
     * 总页数
     */
    private long totalPages;// 一共多少页

    /**
     * 总行数
     */
    private long totalSize;

    public ResultBodyPageVO(int code, String message, T data,long pageNumber,long pageSize,long totalPages,long totalSize) {
        super(code, message, data);
        this.pageNumber = pageNumber;
        this.pageSize = pageSize;
        this.totalSize = totalSize;
        this.totalPages = totalPages;
    }


    public static class CommonPageResultVOBuilder<T>{
        private int code;
        private String message;
        private T data;

        /**
         * 当前页面
         */
        private long pageNumber;// 当前页


        private long pageSize;

        /**
         * 总页数
         */
        private long totalPages;// 一共多少页

        private long totalSize;


        public ResultBodyPageVO.CommonPageResultVOBuilder code(int code){
            this.code = code;
            return this;
        }
        public ResultBodyPageVO.CommonPageResultVOBuilder success(){
            this.code = ResultStatus.SUCCESS.getCode();
            return this;
        }
        public ResultBodyPageVO.CommonPageResultVOBuilder fail(){
            this.code = ResultStatus.FAILED.getCode();
            return this;
        }
        public ResultBodyPageVO.CommonPageResultVOBuilder fail(String message){
            this.code = ResultStatus.FAILED.getCode();
            this.message = message;
            return this;
        }

        public ResultBodyPageVO.CommonPageResultVOBuilder message(String message){
            this.message = message;
            return this;
        }
        public ResultBodyPageVO.CommonPageResultVOBuilder data(T data){
            this.data = data;
            return this;
        }

        public ResultBodyPageVO.CommonPageResultVOBuilder pageNumber(long pageNumber){
            this.pageNumber = pageNumber;
            return this;
        }

        public ResultBodyPageVO.CommonPageResultVOBuilder pageSize(long pageSize){
            this.pageSize = pageSize;
            return this;
        }


        public ResultBodyPageVO.CommonPageResultVOBuilder totalPages(long totalPages){
            this.totalPages = totalPages;
            return this;
        }

        public ResultBodyPageVO.CommonPageResultVOBuilder totalSize(long totalSize){
            this.totalSize = totalSize;
            return this;
        }


        public ResultBodyPageVO<T> build(){
            return new ResultBodyPageVO<T>(code,message,data,pageNumber,pageSize,totalPages,totalSize);
        }
    }


}

 

 

链式调用 lambda 式    

// 区分:
// 链式调用 普通
UpdateChainWrapper<T> update();
// 链式调用 lambda 式。注意:不支持 Kotlin 
LambdaUpdateChainWrapper<T> lambdaUpdate();

// 等价示例:
query().eq("id", value).one();
lambdaQuery().eq(Entity::getId, value).one();

// 等价示例:
update().eq("id", value).remove();
lambdaUpdate().eq(Entity::getId, value).remove();

 上面这个要在service层调用,可以直接获取lambdaQuery()这些对象

 或者使用 Wrappers.lambadQuery(User.class).

 

 

代码生成类

CodeGenerator.java

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

public class CodeGenerator {
    public static void main(String[] args) {

        // 1、创建代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 2、全局配置
        GlobalConfig gc = new GlobalConfig();
        //获取工作目录
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        //作者
        gc.setAuthor("yvioo");
        //生成后是否打开资源管理器
        gc.setOpen(false);
        //重新生成时文件是否覆盖
        gc.setFileOverride(false);
        //去掉Service接口的首字母
        gc.setServiceName("%sService");
        gc.setIdType(IdType.AUTO); //主键策略
        gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
        gc.setSwagger2(false);//开启Swagger2模式

        mpg.setGlobalConfig(gc);

        // 3、数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://1003:3306/mazc?serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("mc");
        dsc.setPassword("Hz56");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 4、包配置
        PackageConfig pc = new PackageConfig();
        //模块名
        pc.setModuleName(null);
        //指定生成的根目录
        pc.setParent("com.test.cms.mybatisplus");

        //以下设置的包名要在上面的目录下

        //控制器的包名
        pc.setController("controller");
        //实体类的包名
        pc.setEntity("entity");

        pc.setService("service");
        //实现类的包名
        pc.setServiceImpl("service.impl");
        //映射文件的包名
        pc.setMapper("mapper");
//xml文件路径        
  pc.setXml("mapper.xml");
mpg.setPackageInfo(pc);
// 5、策略配置 StrategyConfig strategy = new StrategyConfig(); //设置要生成的代码表名 strategy.setInclude("mrevice"); //数据库表映射到实体的命名策略 strategy.setNaming(NamingStrategy.underline_to_camel); //生成实体时去掉表前缀 strategy.setTablePrefix(pc.getModuleName() + "_"); //数据库表字段映射到实体的命名策略 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // lombok 模型 @Accessors(chain = true) setter链式操作 strategy.setEntityLombokModel(true); //restful api风格控制器 strategy.setRestControllerStyle(true); //url中驼峰转连字符 strategy.setControllerMappingHyphenStyle(true); mpg.setStrategy(strategy); // 6、执行 mpg.execute(); } }

 

如果报错

Exception in thread "main" java.lang.NoClassDefFoundError: freemarker/template/Configuration
at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:41)
at com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine.init(FreemarkerTemplateEngine.java:34)
at com.baomidou.mybatisplus.generator.AutoGenerator.execute(AutoGenerator.java:106)
at com.kotei.backend.service.gen.GeneratorCodeConfig.main(GeneratorCodeConfig.java:72)
Caused by: java.lang.ClassNotFoundException: freemarker.template.Configuration
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 4 more

 

添加依赖

 <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
            <scope>compile</scope>
        </dependency>

 

 

自定义数据表和java属性类型

dsc.setTypeConvert(new MySqlTypeConvert() {
            @Override
            public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                System.out.println("转换类型:" + fieldType);
                //tinyint转换成Boolean
                if ( fieldType.toLowerCase().contains( "tinyint" ) ) {
                    return DbColumnType.BOOLEAN;
                }
                //将数据库中datetime转换成date
                if ( fieldType.toLowerCase().contains( "datetime" ) ) {
                    return DbColumnType.DATE;
                }
                return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
            }
        });

 

posted @ 2021-02-25 09:40  yvioo  阅读(1613)  评论(0编辑  收藏  举报