【Mybatis】Mybatis-Plus 高级

news2024/9/27 12:07:38

1、关于插件

1.1、插件机制

        MyBatis 允许你在已映射语句执⾏过程中的某⼀点进⾏拦截调⽤。默认情况下,MyBatis 允许使⽤插件来拦截的⽅法调⽤包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

        我们看到了可以拦截Executor接⼝的部分⽅法,⽐如update,query,commit,rollback等⽅法,还有其他接⼝的⼀些⽅法等。总体概括为:

  1. 拦截执⾏器的⽅法
  2. 拦截参数的处理
  3. 拦截结果集的处理
  4. 拦截Sql语法构建的处理

拦截器示例:

package com.blnp.net.plugin;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import java.util.Properties;

/**
 * <p></p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/27 14:17
 */
@Intercepts(
        @Signature(
                type = Executor.class,
                method = "update",
                args = {MappedStatement.class,Object.class}
        )
)
public class MyInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        /**
         *  拦截方法,具体业务逻辑编写的位置
         **/
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        //创建target对象的代理对象,目的是将当前拦截器加入到该对象中
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {
        //属性设置
    }
}

注入到Spring容器中:

/**
* ⾃定义拦截器
*/
@Bean
public MyInterceptor myInterceptor(){
	return new MyInterceptor();
}

或者通过xml配置,mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<plugins>
		<plugin interceptor="com.blnp.net.plugin.MyInterceptor"></plugin>
	</plugins>
</configuration>

1.2、性能分析插件

1.2.1、旧版本分析方法

        老版本的性能分析插件是使用以下方式来进行分析的,但是该插件比较影响性能。并且官方在3.2.0版本以上已经移除了,但这里还是记录下具体的使用方法:

步骤一:在MP配置类中配置该插件,并且只适用于DEV环境

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

   /*
    *性能分析插件
    */
   @Bean
   @Profile({"dev"}) // 指定环境为dev生效
   public PerformanceInterceptor performanceInterceptor(){
       PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        // 设置sql语句的最大执行时间
       performanceInterceptor.setMaxTime(100);
       // 设置sql是否格式化显示
       performanceInterceptor.setFormat(true);

       return performanceInterceptor;
   }
}

 步骤二:设置环境为dev,可以在yml如下配置,或者直接测试类中也是可以设置的,如图。

spring:
  profiles:
    active: dev

1.2.2、推荐方式

步骤一:引入p6spy的maven依赖

<!--SQL 分析打印-->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.8.2</version>
</dependency>

步骤二:更改yml连接数据库配置,主要修改driver-class-name、url中jdbc后需要加上p6spy

spring:
  datasource:
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:mysql://127.0.0.1:3360/test?userSSL=false
    username: root
    password: 123456
  profiles:
    active: dev

步骤三:新增spy.properties文件,内容如下,可以根据需求相对应的修改文件。

module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
 
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
 
#日志输出到控制台,解开注释就行了
# appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
 
# 指定输出文件位置
logfile=sql.log
 
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
 
# 设置 p6spy driver 代理
deregisterdrivers=true
 
# 取消JDBC URL前缀
useprefix=true
 
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,batch,resultset
 
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
 
# 实际驱动可多个
#driverlist=org.h2.Driver
 
# 是否开启慢SQL记录
outagedetection=true
 
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

步骤四:输出文件格式内容如下

 Consume Time:63 ms 2024-08-27 17:15:22
 Execute SQL:SELECT id,name,age,email FROM user WHERE (age <= '23')

拓展:关于 p6spy

.        P6Spy是一个开源的Java应用程序,它可以拦截和记录JDBC(Java数据库连接)调用,以便开发人员可以更方便地进行数据库调试和性能优化。P6Spy可以通过提供数据库调试信息和SQL执行时间等方面的信息来帮助开发人员诊断慢查询和其他数据库问题。主要包括以下几个方面:

  1. 监视和记录JDBC调用:P6Spy可以拦截JDBC驱动程序发送到数据库的SQL语句,并记录它们以供后期分析。
  2. 统计查询性能:P6Spy可以记录SQL执行时间、连接打开和关闭时间以及事务提交和回滚时间等有关性能的信息。
  3. 分析慢查询:P6Spy可以帮助开发人员查找和调试缓慢的SQL查询,以便优化查询性能。
  4. 预测系统行为:使用P6Spy,开发人员可以获得有关系统负载和数据库性能的信息,以便优化系统配置和资源使用。

相关配置:

# 指定应用的日志拦截模块,默认为com.p6spy.engine.spy.P6SpyFactory 
#modulelist=com.p6spy.engine.spy.P6SpyFactory,com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory

# 真实JDBC driver , 多个以 逗号 分割 默认为空
#driverlist=

# 是否自动刷新 默认 flase
#autoflush=false

# 配置SimpleDateFormat日期格式 默认为空
#dateformat=

# 打印堆栈跟踪信息 默认flase
#stacktrace=false

# 如果 stacktrace=true,则可以指定具体的类名来进行过滤。
#stacktraceclass=

# 监测属性配置文件是否进行重新加载
#reloadproperties=false

# 属性配置文件重新加载的时间间隔,单位:秒 默认60s
#reloadpropertiesinterval=60

# 指定 Log 的 appender,取值:
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
#appender=com.p6spy.engine.spy.appender.StdoutLogger
#appender=com.p6spy.engine.spy.appender.FileLogger

# 指定 Log 的文件名 默认 spy.log
#logfile=spy.log

# 指定是否每次是增加 Log,设置为 false 则每次都会先进行清空 默认true
#append=true

# 指定日志输出样式  默认为com.p6spy.engine.spy.appender.SingleLineFormat , 单行输出 不格式化语句
#logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat
# 也可以采用  com.p6spy.engine.spy.appender.CustomLineFormat 来自定义输出样式, 默认值是%(currentTime)|%(executionTime)|%(category)|connection%(connectionId)|%(sqlSingleLine)
# 可用的变量为:
#   %(connectionId)            connection id
#   %(currentTime)             当前时间
#   %(executionTime)           执行耗时
#   %(category)                执行分组
#   %(effectiveSql)            提交的SQL 换行
#   %(effectiveSqlSingleLine)  提交的SQL 不换行显示
#   %(sql)                     执行的真实SQL语句,已替换占位
#   %(sqlSingleLine)           执行的真实SQL语句,已替换占位 不换行显示
#customLogMessageFormat=%(currentTime)|%(executionTime)|%(category)|connection%(connectionId)|%(sqlSingleLine)

# date类型字段记录日志时使用的日期格式 默认dd-MMM-yy
#databaseDialectDateFormat=dd-MMM-yy

# boolean类型字段记录日志时使用的日期格式 默认boolean 可选值numeric
#databaseDialectBooleanFormat=boolean

# 是否通过jmx暴露属性 默认true
#jmx=true

# 如果jmx设置为true 指定通过jmx暴露属性时的前缀 默认为空
# com.p6spy(.<jmxPrefix>)?:name=<optionsClassName>
#jmxPrefix=

# 是否显示纳秒 默认false
#useNanoTime=false

# 实际数据源 JNDI
#realdatasource=/RealMySqlDS
# 实际数据源 datasource class
#realdatasourceclass=com.mysql.jdbc.jdbc2.optional.MysqlDataSource

# 实际数据源所携带的配置参数 以 k=v 方式指定 以 分号 分割
#realdatasourceproperties=port;3306,serverName;myhost,databaseName;jbossdb,foo;bar

# jndi数据源配置 
# 设置 JNDI 数据源的 NamingContextFactory。 
#jndicontextfactory=org.jnp.interfaces.NamingContextFactory
# 设置 JNDI 数据源的提供者的 URL。 
#jndicontextproviderurl=localhost:1099
# 设置 JNDI 数据源的一些定制信息,以分号分隔。 
#jndicontextcustom=java.naming.factory.url.pkgs;org.jboss.naming:org.jnp.interfaces

# 是否开启日志过滤 默认false, 这项配置是否生效前提是配置了 include/exclude/sqlexpression
#filter=false

# 过滤 Log 时所包含的表名列表,以逗号分隔 默认为空
#include=
# 过滤 Log 时所排除的表名列表,以逗号分隔 默认为空
#exclude=

# 过滤 Log 时的 SQL 正则表达式名称  默认为空
#sqlexpression=

#显示指定过滤 Log 时排队的分类列表,取值: error, info, batch, debug, statement,
#commit, rollback, result and resultset are valid values
# (默认 info,debug,result,resultset,batch)
#excludecategories=info,debug,result,resultset,batch

# 是否过滤二进制字段
# (default is false)
#excludebinary=false

# P6Log 模块执行时间设置,整数值 (以毫秒为单位),只有当超过这个时间才进行记录 Log。 默认为0
#executionThreshold=

# P6Outage 模块是否记录较长时间运行的语句 默认false
# outagedetection=true|false
# P6Outage 模块执行时间设置,整数值 (以秒为单位)),只有当超过这个时间才进行记录 Log。 默认30s
# outagedetectioninterval=integer time (seconds)

1.3、乐观锁插件

1.3.1、适用场景

        目的是当要更新⼀条记录的时候,希望这条记录没有被别⼈更新。乐观锁实现⽅式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执⾏更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

1.3.2、插件配置

SpringBoot:

@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    return new OptimisticLockerInterceptor();
}

SpringMVC:

<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>

1.3.3、注解实体字段

第⼀步,为表添加version字段,并且设置初始值为1:

ALTER TABLE `tb_user`
ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE `tb_user` SET `version`='1';

第⼆步,为User实体对象添加version字段,并且添加@Version注解:

@Version
private Integer version;

1.3.4、验证测试

@Test
public void testUpdate() {
    User user = new User();
    user.setAge(30);
    user.setId(2 L);
    user.setVersion(1); //获取到version为1
    int result = this.userMapper.updateById(user);
    System.out.println("result = " + result);
}
[DEBUG] Original SQL: UPDATE tb_user SET age=?,
version=? WHERE id=? AND version=?
[main] [com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser]-
[DEBUG] parser sql: UPDATE tb_user SET age = ?, version = ? WHERE id = ? AND
version = ?
[main] [org.springframework.jdbc.datasource.DataSourceUtils]-[DEBUG] Fetching
JDBC Connection from DataSource
[main] [org.mybatis.spring.transaction.SpringManagedTransaction]-[DEBUG] JDBC
Connection [HikariProxyConnection@540206885 wrapping
com.mysql.jdbc.JDBC4Connection@27e0f2f5] will not be managed by Spring
[main] [com.blnp.net.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Preparing:
UPDATE tb_user SET age=?, version=? WHERE id=? AND version=?
[main] [com.blnp.net.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Parameters:
30(Integer), 2(Integer), 2(Long), 1(Integer)
[main] [com.blnp.net.mp.mapper.UserMapper.updateById]-[DEBUG] <== Updates: 1
[main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30135202]
result = 1

1.3.5、特别说明

  • ⽀持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity 中
  • 仅⽀持 updateById(id) 与 update(entity, wrapper) ⽅法
  • 在 update(entity, wrapper) ⽅法下, wrapper 不能复⽤!!!

2、SQL 注入器

2.1、编写MyBaseMapper

package com.blnp.net.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.util.List;

/**
 * <p></p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/28 9:06
 */
public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 用途: 自定义查询所有接口
     * @author liaoyibin
     * @since 9:11 2024/8/28
     * @params []
     * @param
     * @return java.util.List<T>
    **/
    List<T> findAll();
}

        实际使用时,对应的mapper继承该自定义mapper即可:

2.2、编写MySqlInjector

        如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的⽅法将失效,所以我们选择继承DefaultSqlInjector进⾏扩展。

package com.blnp.net.sqlInjector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 自定义SQL注入方法
 * <p>
 *     1、直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效
 * </p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/28 9:17
 */
@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        //注入自定义SQL方法实现
        methodList.add(new FindAll());
        return methodList;
    }
}

2.3、编写FindAll

package com.blnp.net.sqlInjector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

/**
 * <p></p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/28 9:25
 */
public class FindAll extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sqlMethod = "findAll";
        String sql = "select * from " + tableInfo.getTableName();
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addSelectMappedStatementForTable(mapperClass, sqlMethod, sqlSource, tableInfo);
    }
}

2.4、注册到Spring容器

@Bean
public ISqlInjector mySqlInjector() {
    return new MySqlInjector();
}

2.5、测试验证

package com.blnp.net.mp;

import com.blnp.net.mp.generator.project.entity.TbProject;
import com.blnp.net.mp.generator.project.mapper.TbProjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class GeneratorCodeApplicationTests {

    @Resource
    TbProjectMapper projectMapper;

    /**
     * 用途:乐观锁测试实现
     * @author liaoyibin
     * @since 14:48 2024/8/28
     * @params []
     * @param
     * @return void
    **/
    @Test
    public void contextLoads() {
        TbProject project = projectMapper.selectById(1);
        project.setCreater("李四");
        int i = projectMapper.updateById(project);
        System.out.println("i = " + i);

        /**
         *  特别说明:
         *      这里尤其要注意,关于Mybatis-Plus的乐观锁插件,仅支持 updateById(id) 与 update(entity, wrapper) 方法;
         *   此外,如果是单独 new 对象实体的方式进行更新是不会触发乐观锁的。
         *
         *   UserEntity entity = new UserEntity();
         *   entity.setId(1);
         *   mapper.updateById(entity);
         *   //该方式是无效且不触发乐观锁!!
         **/
    }

    /**
     * 用途:SQL注入器测试查询
     * @author liaoyibin
     * @since 14:47 2024/8/28
     * @params []
     * @param
     * @return void
    **/
    @Test
    public void testCusQuery() {
        List<TbProject> tbProjects = projectMapper.findAll();
        for (TbProject tbProject : tbProjects) {
            System.out.println("tbProject = " + tbProject);
        }
    }
}

3、自动填充功能

3.1、添加@TableField注解

        有些时候我们可能会有这样的需求,插⼊或者更新数据时,希望有些字段可以⾃动填充数据,⽐如密码、version等。在MP中提供了这样的功能,可以实现⾃动填充。

package com.baomidou.mybatisplus.annotation;

/**
 * 字段填充策略枚举类
 *
 * <p>
 * 判断注入的 insert 和 update 的 sql 脚本是否在对应情况下忽略掉字段的 if 标签生成
 * <if test="...">......</if>
 * 判断优先级比 {@link FieldStrategy} 高
 * </p>
 *
 * @author hubin
 * @since 2017-06-27
 */
public enum FieldFill {
    /**
     * 默认不处理
     */
    DEFAULT,
    /**
     * 插入时填充字段
     */
    INSERT,
    /**
     * 更新时填充字段
     */
    UPDATE,
    /**
     * 插入和更新时填充字段
     */
    INSERT_UPDATE
}

3.2、编写MyMetaObjectHandler

package com.blnp.net.mp.generator.handle;

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

import java.util.Optional;

/**
 * <p>自动填充插件实现</p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/28 14:54
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        Object creater = getFieldValByName("creater", metaObject);
        if (!Optional.ofNullable(creater).isPresent()) {
            //新增SQL时,为空则自动填充
            setFieldValByName("creater","王二麻子",metaObject);
        }
        Object createTime = getFieldValByName("createTime", metaObject);
        if (!Optional.ofNullable(createTime).isPresent()) {
            //新增SQL时,为空则自动填充
            long currentTimeMillis = System.currentTimeMillis();
            setFieldValByName("createTime",currentTimeMillis,metaObject);
        }
        Object comment = getFieldValByName("comment", metaObject);
        if (!Optional.ofNullable(comment).isPresent()) {
            //新增SQL时,为空则自动填充
            String commentMsg = String.format("记录于 %s 时刻,完成【新增】操作!", DateUtil.now());
            setFieldValByName("comment",commentMsg,metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        Object comment = getFieldValByName("comment", metaObject);
        if (!Optional.ofNullable(comment).isPresent()) {
            //新增SQL时,为空则自动填充
            String commentMsg = String.format("记录于 %s 时刻,完成【更新】操作!", DateUtil.now());
            setFieldValByName("comment",commentMsg,metaObject);
        }
    }
}

 3.3、验证测试

@Test
public void testAutoFill() {
    TbProject project = new TbProject();
    project.setName("喷淋系统");
    int insert = projectMapper.insert(project);
    System.out.println("project = " + project);
}

4、逻辑删除

4.1、修改表结构

        为数据表增加deleted字段,⽤于表示数据是否被删除,1代表删除,0代表未删除。同时,也修改User实体,增加deleted属性并且添加@TableLogic注解:

ALTER TABLE `tb_user`
ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除'
AFTER `version`;
@TableLogic
private Integer deleted;

4.2、配置

application.properties:

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

 4.3、测试验证

@Test
public void testLogicDelete() {
    int deleteById = projectMapper.deleteById(2);
    System.out.println("deleteById = " + deleteById);
}

5、代码生成器

5.1、创建Maven工程

        并配置以下版本依赖:

<properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--mybatis-plus的springboot⽀持-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--简化代码的具包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

5.2、创建生成类

package com.blnp.net.mp.generator;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
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.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

/**
 * <p>mysql代码生成器示例</p>
 *
 * @author lyb 2045165565@qq.com
 * @version 1.0
 * @since 2024/8/28 11:07
 */
public class MysqlGenerator {

    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("blnp");
        gc.setOpen(false);
        mpg.setGlobalConfig(gc);
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://127.0.0.1:3307/my_test?useUnicode=true&useSSL=false&characterEncoding=utf8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("admin@123");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(scanner("模块名"));
        pc.setParent("com.blnp.net.mp.generator");
        mpg.setPackageInfo(pc);

        //自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //自定义输入文件名称
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" +
                        StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        mpg.setTemplate(new TemplateConfig().setXml(null));

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity");
        strategy.setEntityLombokModel(true);
        //strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController");
        strategy.setInclude(scanner("表名"));
        strategy.setSuperEntityColumns("id");
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        // 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}

5.3、生成测试

5.4、示例源代码

示例源代码下载:

generator-code.7z官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘

6、完整源代码

mybatis-plus示例包.7z官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2088774.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vTESTstudio系列12--vTESTstudio中的动态函数库介绍2

在上期的文章&#xff08;vTESTstudio系列11--vTESTstudio中的动态函数库介绍1&#xff09;中&#xff0c;我们详细介绍了osek_tp.dll的接口&#xff0c;本章开始给大家介绍如何通过osek_tp.dll的接口去发送诊断指令&#xff0c;Let‘s Go!!! 目录 1. CanTp发送数据的函数&am…

插件千兆网络变压器72PIN应用图片和设计H87202D

华强盛电子导读&#xff1a;前面199中间2643后面0038 千兆4口网络变压器是一种常用于网络通信领域的电子元件&#xff0c;它可以将高频率的信号进行隔离和滤波&#xff0c;保护网络设备免受电磁干扰&#xff0c;同时也能确保信号的稳定传输。这种网络变压器通常具有多个端口&am…

使用tyarn下载依赖出现: 无法加载文件 D:\environment_software\nvm_node\tyarn.ps1,因为在此系统上禁止运行脚本。

使用tyarn下载依赖时出现&#xff1a; 无法加载文件 D:\environment_software\nvm_node\tyarn.ps1&#xff0c;因为在此系统上禁止运行脚本。 表示window不能执行ps1文件&#xff0c;可以通过设置命令运行执行ps1文件&#xff08;PowerShell&#xff09;。输入命令查看配置&am…

程序设计—智慧城市应急物资配送系统开发—车辆调度 项目源码36262

摘 要 在智慧城市建设的浪潮中&#xff0c;应急物资配送系统的车辆调度模块扮演着举足轻重的角色。该模块通过集成先进的信息技术和管理理念&#xff0c;实现了对配送地区、前置仓、车辆资源以及调度信息的全面管理和优化&#xff0c;从而确保在紧急情况下能够迅速、准确地将应…

自动生成文章的软件,提高你写文章的效率

对于每个写作人员而言&#xff0c;如果在写作中有一个工具可以协助提高工作效率&#xff0c;想必大家是都乐意接受的&#xff0c;那么今天小编就在本文中为大家分享一个好用的自动生成文章的软件&#xff0c;它可以在大家没有写作灵感时用来自动生成文章用&#xff0c;同时也可…

JVM中篇:字节码与类的加载篇-04-再谈类的加载器

笔记来源&#xff1a;尚硅谷JVM全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解java虚拟机&#xff09; 文章目录 1. 概述1.1. 大厂面试题1.2. 类加载器的分类1.3. 类加载器的必要性1.4. 命名空间1.5. 类加载机制的基本特征1.6. 类加载器之间的关系 2…

视频结构化从入门到精通——图像算法类型介绍

视频结构化主要图像算法 1 认识“数组、矩阵和张量” 1.1 什么是维度 在图像算法中&#xff0c;“维度”这个概念非常重要&#xff0c;它描述了数据的结构和形状。在不同的上下文中&#xff0c;维度可能有不同的含义&#xff0c;但总体来说&#xff0c;它们都与数据的排列方式…

【已解决】git@github.com: Permission denied (publickey).处理git 无权限访问问题

解决思路 分析 gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository. 意译&#xff1a;权限拒绝&#xff08;公开密钥&#xff09;&#xff0c;后果&#xff1a;无法读远程仓库。 人话&#xff1a;GitHub设置里面的公钥没有配置或者…

关于武汉芯景科技有限公司的实时时钟芯片XJ8339开发指南(兼容DS1339)

一、芯片引脚介绍 1.芯片引脚 2.引脚描述 二、系统结构图 三、功能描述 1.时钟功能 2.闹钟功能&#xff08;两个闹钟&#xff09; 3.振荡器停止控制 4.频率输出&#xff08;1HZ、1.096KHZ、8.192KHZ、32.768KHZ&#xff09; 5.振荡器停止检测 6.闹钟中断标志 7.涓流充电…

领英(LinkedIn)无法开发会员客户?一招教你轻松解决

经常会有外贸朋友问我&#xff0c;领英会员的客户要怎么开发&#xff0c;如果不开会员的就无法添加好友&#xff0c;查看信息等等&#xff0c;经过我的反复实践&#xff0c;今天给大家分享一个超级好用的开发领英会员的方法&#xff0c;不需要开领英会员一样可以轻松开发&#…

【网络安全】服务基础第一阶段——第六节:Windows系统管理基础---- DNS部署与安全

计算机智能识别并用IP地址定位&#xff0c;例如我们想要访问一个网页&#xff0c;其实是只能使用这个网页的IP地址&#xff0c;即四位的0&#xff5e;255来访问&#xff0c;但这一串数字难以记忆&#xff0c;于是就有了DNS&#xff0c;将难以记忆的数字转化为容易记忆的域名&am…

【栈】| 力扣高频题: 基本计算器二

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;算法题 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/basic-calculator-ii/description/ (可点击) 本道题是栈…

Docker 镜像导出与加载:从入门到精通

在容器化技术的世界中&#xff0c;Docker 镜像的导出与加载是开发与运维人员经常会用到的技能。本文将详细介绍如何导出 Docker 镜像为本地 tar 文件&#xff0c;并如何将其重新加载为 Docker 镜像&#xff0c;并分享一些操作中的小技巧与趣味总结。 一、Docker 镜像导出的秘…

Spring Security基于token的极简示例

1 引言 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架&#xff0c;但是用起来有点复杂&#xff0c;为了便于学习理解&#xff0c;下面将用最简洁的配置和示例&#xff0c;展示整个流程。 2 代码 创建一个spring-security…

深入理解 XSS 漏洞:原理、危害与防范

在网络安全领域&#xff0c;跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;XSS&#xff09;一直是一个备受关注的问题。XSS 漏洞的存在可能导致严重的安全后果&#xff0c;影响网站的正常运行和用户的信息安全。本文将深入探讨 XSS 漏洞的原理、危害以及有效的防范…

Mysql在服务器中的源码部署

1.在Linux下部署mysql 1.安装依赖性 [rootmysql1 ~]# dnf install cmake gcc-c openssl-devel \ ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 2.下载并解压源码包 [rootmysql1 ~]# tar zxf mysql-boost-5.7.44.tar.gz [rootmysql1 ~]# cd…

讲述Navicat for MySQL定时备份数据库和数据恢复等功能

一. 设置计划任务定时备份数据库 计划任务就是让电脑在指定的时间内执行指定的动作&#xff0c;这些动作可以是一个程序&#xff0c;也可以是一个批处理&#xff0c;但是至少是可以运行的&#xff01;其实再通俗一点也就是相当于你在那个时间里面进行了对某个东西对鼠标双击的…

Android 开发兼容性问题,TaskExecutionException等问题。

1、问题描述&#xff1a; kapt com.github.bumptech.glide:compiler:4.12.0 org.gradle.api.tasks.TaskExecutionException: Execution failed for task :app:kaptJlbDebugKotlin. 2、问题分析&#xff1a; 如果多人协作开发&#xff0c;从仓库 clone \ 下载的项目代码&…

6个装进手机里能涨知识的手机应用app,每个都有大学问!

分享6个装进手机里能涨知识的手机应用app&#xff0c;每个都有大学问&#xff01; 1.TED 一个著名的演讲平台&#xff0c;它汇集了全球众多领域专家和思想领袖的精彩演讲。这些演讲覆盖了科技、艺术、设计、心理学、教育等多个领域&#xff0c;为观众提供了丰富的知识和启发性…

网络安全人才缺口大 每年相关专业毕业生仅8千余人

&#x1f91f; 基于入门网络安全打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 “目前我国网络安全方面人才缺口仍然很大&#xff0c;相关专业每年本科、硕士、博士毕业生之和仅8000余人&#xff0c;而我国网民数量近7亿人。”网信办网络安全…