Mybatisplus生成代码配置 p6spy打印sql mybatis日志打印 mybatisplus用法

本文主要是介绍Mybatisplus生成代码配置 p6spy打印sql mybatis日志打印 mybatisplus用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 学习链接
    • 代码生成 & p6spy打印sql
      • 1. pom.xml
      • 2. application.yml
      • 3. spy.properties
      • 注意事项
      • 4. MyBatisPlusGenCode
    • mybatis日志打印
      • 原理分析
      • 示例
        • logback-spring.xml
        • application.yml
    • 使用
      • @Tableld
      • ==@TableField==
        • mybatisplus 插入/修改 用法
          • 插入(或新增)
          • 修改(或更新)
          • 插入或修改
      • FieldStrategy
        • IGNORED
        • NOT_NULL
        • NOT_EMPTY
        • DEFAULT
        • NEVER
      • FieldFill
        • 自动填充字段
          • UserEntity
          • 定义MetaObjectHandler
          • 使用
          • 注意事项

学习链接

mybatisplus官网

MyBatis Plus详细教程

Mybatis Plus 看这篇就够了,通俗易懂,一发入魂

LogBack日志

【mybatis plus源码解析】(一)mybatis plus执行原理,mybatis plus是如何实现自动注入CRUD操作

【mybatis plus源码解析】(二)详解SQL注入器底层原理,mybatis plus是如何实现自动注入CRUD操作

【mybatis plus源码解析】(三)自定义SQL注入器,教你如何自定义扩展BaseMapper接口方法,实现更多查询

代码生成 & p6spy打印sql

1. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.zzhua</groupId><artifactId>demo-mybatisplus</artifactId><version>0.0.1-SNAPSHOT</version><name>demo-mybatisplus</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.3</version></dependency><dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency><!--swagger2依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version> 2.7.0</version></dependency><!--swagger-ui第三方依赖--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

2. application.yml

spring:datasource:
#    driver-class-name: com.mysql.jdbc.Driverdriver-class-name: com.p6spy.engine.spy.P6SpyDriverurl: jdbc:p6spy:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: root

3. spy.properties

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 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,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

注意事项

  • driver-class-name 为 p6spy 提供的驱动类
  • url 前缀为 jdbc:p6spy 跟着冒号为对应数据库连接地址
  • 打印出 sql 为 null,在 excludecategories 增加 commit
  • 批量操作不打印 sql,去除 excludecategories 中的 batch
  • 批量操作打印重复的问题请使用 MybatisPlusLogFactory (3.2.1 新增)
  • 该插件有性能损耗,不建议生产环境使用。

4. MyBatisPlusGenCode

package com.zzhua.generator;import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import java.util.Collections;/*** @description* @Author: zzhua* @Date 2022/8/15*/
public class MyBatisPlusGenCode {public static void main(String[] args) {FastAutoGenerator.create("jdbc:p6spy:mysql://127.0.0.1:3306/mytest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true","root", "root").globalConfig(builder -> {builder.author("zzhua") // 设置作者.fileOverride() // 覆盖已生成文件.enableSwagger() // 开启 swagger 模式.dateType(DateType.ONLY_DATE).disableOpenDir().outputDir("D:\\projects\\demo-mybatisplus\\src\\main\\java"); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.zzhua") // 设置父包名.moduleName("system") // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml, "D:\\projects\\demo-mybatisplus\\src\\main\\resources\\mapper")); // 设置mapperXml生成路径}).strategyConfig(builder -> {builder.addInclude("my_user") // 设置需要生成的表名// .addTablePrefix("t_", "c_"); // 设置过滤表前缀.entityBuilder().enableFileOverride().enableLombok()// .enableTableFieldAnnotation().naming(NamingStrategy.underline_to_camel).idType(IdType.AUTO).convertFileName(name->name.concat("Entity")).controllerBuilder().enableFileOverride().enableRestStyle().mapperBuilder().enableFileOverride().enableBaseColumnList().enableBaseResultMap();}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}

mybatis日志打印

原理分析

在这里插入图片描述

  • 当以上配好确定了日志的构造器后,mybatis中的所有打印日志的地方,都会直接的从Mybatis自己的日志工厂类中获取日志输出对象。

  • 而确定构造器的过程就是查找当前项目中,所能够支持的具体实现。项目一启动,mybatis在LogFactory的静态方法中,就会去按左边的列表,挨个尝试,看哪个能够创建成功,第一个创建成功的,则会设置为确定的构造器。

  • 也可以手动设置Configuration的logImpl,实际上就等价于在修改LogFactory的logConstructor的实现。

还有重要的一点,要留意到:在MappedStatement.Builder中给MappedStatement设置statementLog对象的时候,就是直接使用的LogFactory.getLog(logId),其中的这个logId就是当前sql语句所在的命名空间拼接上当前sql的id,后面很多打印sql相关的日志,其实就是把这个statementLog传来传去的在用statementLog。并且,mybatis的日志打印实际上它还通过动态代理的方式,给原来的对象包了一层,将日志打印的逻辑嵌入到了其中,具体的日志打印交给了以BaseJdbcLogger为抽象父类,子类有:StatementLogger、ConnectionLogger、ResultSetLogger、PreparedStatementLogger打印的。

当以上mybatis日志相关的配置原理理解了之后,我们发现真正的日志打印,mybatis其实并没有帮我们做,它只是写了个类,日志的具体输出就桥接给了真正的日志实现。所以开始初学mybatis时,也是比较头疼的问题,有的时候,能打印出日志,有的时候打印不出来日志,现在就知道为啥了。

示例

在项目里面,我们可以直接配置configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl,将sql直接打印输出在控制台,它里面的实现就是不管什么级别的输出日志,就是调用System.out.println(s) 或 System.err.println(s);直接打印在控制台上。这个实现感觉也不那么好用:它的trace是打开的,也就是说在查询语句中,它老是把Columns:…,Row:…全特么给打印出来,有的时候,数据一多,看着不爽,而且我们没办法改变它里面的属性。我们有2种办法解决这个问题,1:可以自己复制它这个类,然后手动改了它的默认方法,比如把traceEnabled的返回值改为false,然后指定 为我们的实现类。2:换个org.apache.ibatis.logging.slf4j.Slf4jImpl的实现,然后,就可以结合logback来玩了(可参考:LogBack日志
),也可以把sql输出到控制到,把sql日志单独输出到一个文件中也可以,还可以指定日志器的输出级别,特别方便,推荐使用这种方式。

logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false"><include resource="org/springframework/boot/logging/logback/defaults.xml" /><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--><property name="LOG_BASE_PATH" value="logs" /><property name="maxFileSize" value="5MB"/><property name="maxHistory" value="30"/><!--<property name="commonPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}-${PID}-[%X{X-B3-TraceId},%X{X-B3-SpanId},%X{X-B3-ParentSpanId}]-[%thread] %-5level %logger{30} [%file:%line] - %msg%n"/>--><!--控制台日志, 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>${CONSOLE_LOG_PATTERN}</pattern></encoder></appender><!--文件日志, 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_BASE_PATH}/vue-springboot.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名--><FileNamePattern>${LOG_BASE_PATH}/%d/xxx.log.%d{yyyy-MM-dd}-%i.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>${maxHistory}</MaxHistory><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>${maxFileSize}</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>${FILE_LOG_PATTERN}</pattern></encoder></appender><!-- 在这里可以修改日志级别 --><logger name="com.zzhua.mapper" level="trace" additivity="false"><appender-ref ref="STDOUT" /></logger><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="STDOUT" /><appender-ref ref="FILE"/></root></configuration>
application.yml
server:port: 8085servlet:context-path:
spring:datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/vue-springboot?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8username: rootpassword: rootservlet:multipart:max-file-size: 50MBmax-request-size: 50MBmybatis-plus:mapper-locations: classpath:/mapper/**.xmlconfiguration:log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl

使用

@Tableld

/*** 表主键标识*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {/*** 字段名(该值可无)*/String value() default "";/*** 主键类型* {@link IdType}*/IdType type() default IdType.NONE;
}

@TableField

/*** 表字段标识*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {/*** 数据库字段值* <p>* 不需要配置该值的情况:* <li> 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 true 时,* (mp下默认是true,mybatis默认是false), 数据库字段值.replace("_","").toUpperCase() == 实体属性名.toUpperCase() </li>* <li> 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 false 时,* 数据库字段值.toUpperCase() == 实体属性名.toUpperCase() </li>*/String value() default "";/*** 是否为数据库表字段* <p>* 默认 true 存在,false 不存在*/boolean exist() default true;/*** 字段 where 实体查询比较条件* <p>* 默认 {@link SqlCondition#EQUAL}*/String condition() default "";/*** 字段 update set 部分注入, 该注解优于 el 注解使用* <p>* 例1:@TableField(.. , update="%s+1") 其中 %s 会填充为字段* 输出 SQL 为:update 表 set 字段=字段+1 where ...* <p>* 例2:@TableField(.. , update="now()") 使用数据库时间* 输出 SQL 为:update 表 set 字段=now() where ...*/String update() default "";/*** 字段验证策略之 insert: 当insert操作时,该字段拼接insert语句时的策略* <p>* IGNORED: 直接拼接 insert into table_a(column) values (#{columnProperty});* NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)* NOT_EMPTY: insert into table_a(<if test="columnProperty != null and columnProperty!=''">column</if>) values (<if test="columnProperty != null and columnProperty!=''">#{columnProperty}</if>)* NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL** @since 3.1.2*/FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;/*** 字段验证策略之 update: 当更新操作时,该字段拼接set语句时的策略* <p>* IGNORED: 直接拼接 update table_a set column=#{columnProperty}, 属性为null/空string都会被set进去* NOT_NULL: update table_a set <if test="columnProperty != null">column=#{columnProperty}</if>* NOT_EMPTY: update table_a set <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>* NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL** @since 3.1.2*/FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;/*** 字段验证策略之 where: 表示该字段在拼接where条件时的策略* <p>* IGNORED: 直接拼接 column=#{columnProperty}* NOT_NULL: <if test="columnProperty != null">column=#{columnProperty}</if>* NOT_EMPTY: <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>* NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL** @since 3.1.2*/FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;/*** 字段自动填充策略* <p>* 在对应模式下将会忽略 insertStrategy 或 updateStrategy 的配置,等于断言该字段必有值*/FieldFill fill() default FieldFill.DEFAULT;/*** 是否进行 select 查询* <p>* 大字段可设置为 false 不加入 select 查询范围*/boolean select() default true;/*** 是否保持使用全局的 columnFormat 的值* <p>* 只生效于 既设置了全局的 columnFormat 也设置了上面 {@link #value()} 的值* 如果是 false , 全局的 columnFormat 不生效** @since 3.1.1*/boolean keepGlobalFormat() default false;/*** {@link ResultMapping#property} and {@link ParameterMapping#property}** @since 3.4.4*/String property() default "";/*** JDBC类型 (该默认值不代表会按照该值生效),* 只生效于 mp 自动注入的 method,* 建议配合 {@link TableName#autoResultMap()} 一起使用* <p>* {@link ResultMapping#jdbcType} and {@link ParameterMapping#jdbcType}** @since 3.1.2*/JdbcType jdbcType() default JdbcType.UNDEFINED;/*** 类型处理器 (该默认值不代表会按照该值生效),* 只生效于 mp 自动注入的 method,* 建议配合 {@link TableName#autoResultMap()} 一起使用* <p>* {@link ResultMapping#typeHandler} and {@link ParameterMapping#typeHandler}** @since 3.1.2*/Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;/*** 只在使用了 {@link #typeHandler()} 时判断是否辅助追加 javaType* <p>* 一般情况下不推荐使用* {@link ParameterMapping#javaType}** @since 3.4.0 @2020-07-23*/boolean javaType() default false;/*** 指定小数点后保留的位数,* 只生效于 mp 自动注入的 method,* 建议配合 {@link TableName#autoResultMap()} 一起使用* <p>* {@link ParameterMapping#numericScale}** @since 3.1.2*/String numericScale() default "";
}
mybatisplus 插入/修改 用法
插入(或新增)
  • userMapper.insert(userEntity)
    • 将会插入userEntity对象中属性值不为null的字段
  • userService.save(new UserEntity())
    • 将会插入userEntity对象中属性值不为null的字段 ,其实就是调用userMapper.insert(userEntity)
修改(或更新)
  • userMapper.updateById(userEntity)
    • 以where id = #{userEntity.id} 为条件,userEntity对象中 属性值不为null的字段作为set,组成sql
  • userMapper.update(userEntity, new UpdateWrapper<userEntity>().lambda().eq( UserEntity::getNickname, "zzhua"));
    • 以后面updateWrapper指定的字段作为where条件,并且以userEntity对象中 属性值不为null的字段作为set,组成sql
    • 后面的updateWrapper不仅可以指定作为where条件的字段,还可以设置sql字段的值(这也会拼接到最终的sql上,并且这如果和userEntity对象的属性重复了,这里的顺序会在后面,所以会以这里的生效),可以考虑使用QueryWrapper,这样就没有设置sql字段的方法了。
    • 注意上面Wrapper需要设置表对应的实体类 作为泛型
  • userService.updateById(userEntity)
    • 将会以where id = #{userEntity.id} 为条件,插入userEntity对象中属性值不为null的字段 ,其实就是调用userMapper.insert(userEntity)
  • userService.update(user, new UpdateWrapper<User>().lambda().eq( User::getNickname, "zzhua"))
    • 其实就是调用userMapper.update(userEntity, new UpdateWrapper<userEntity>().lambda().eq( UserEntity::getNickname, "zzhua")),所以用法完全与它相同
  • userService.update(new UpdateWrapper<User>().lambda().eq(User::getNickname, "zzhua195").set(User::getIsV, 10))
    • 其实就是调用 userService.update(user,updateWrapper)),只不过这里的user是null,即等价于:userService.update(null , updateWrapper))
    • 直接以UpdateWrapper调用方法确定更新的where条件 和 使用set更新字段的值
  • userService.lambdaUpdate().set(User::getIsV, 55).eq(User::getNickname, "zzhua195").update()
    • 以链式的方式使用mybatisplus
    • 这种写法有两次出现update()方法哦,但不是同一个update()方法 ,前面的update()方法是开启链式调用的开端,后面的update一定要调用,否则不会执行sql
    • 最后面的update方法中可以传入一个userEntity对象,其中userEntity对象中的属性值不为null的属性将会设置作为更新的字段。当然,也可以不传入。如果传入了一个userEntity对象,并且遇到与前面设置的字段有冲突,最后都会加入到sql中,但是前面设置的会出现在sql的后面位置,因此,前面设置更优先。
  • userService.update().eq("nickname", "zzhua195").set("avatarUrl", "urll").update()
    • 以链式的方式使用mybatisplus,这种用法需要把字段名写准确(不能写错,因此不推荐使用,万一后面改字段名了,就废了),可以简单理解为:不带lambda的话,那就要写具体的数据库字段名
    • 这种写法有两次出现update()方法哦,但不是同一个update()方法 ,前面的update()方法是开启链式调用的开端,后面的update一定要调用,否则不会执行sql
    • 最后面的update方法中可以传入一个userEntity对象,其中userEntity对象中的属性值不为null的属性将会设置作为更新的字段。当然,也可以不传入。如果传入了一个userEntity对象,并且遇到与前面设置的字段有冲突,最后都会加入到sql中,但是前面设置的会出现在sql的后面位置,因此,前面设置更优先。
插入或修改
  • userService.saveOrUpdate(userEntity)
    • 先去获取userEntity的主键,如果主键为null或者为空字符串(即没有指定主键),那么就一定是插入,使用baseMapper.insert(userEntity)插入数据。如果指定了主键,那么会调用baseMapper.selectById(id)方法,根据主键查询是否存在,如果不存在,则执行baseMapper.insert(userEntity)插入数据,如果存在,则执行baseMapper.updateById(userEntity)
  • userService.saveOrUpdate(userEntity, new UpdateWrapper<UserEntity>().lambda().eq(UserEntity::getNickname, "zzhua195").set(UserEntity::getCreateTime, new Date()))
    • 先尝试调用baseMapper.update(entity,updateWrapper),如果这个结果返回的是的数量大于等于1,那么直接返回true,这个saveOrUpdate就执行完了。但是如果这个结果返回的数量没有超过1(未更新到数据),那么就会去执行userService.saveOrUpdate(userEntity),注意这个时候就跟updateWrapper没什么关系了。

FieldStrategy

IGNORED
NOT_NULL
NOT_EMPTY
DEFAULT
NEVER
/*** 字段策略枚举类* <p>* 如果字段是基本数据类型则最终效果等同于 {@link #IGNORED}** @author hubin* @since 2016-09-09*/
public enum FieldStrategy {/*** 忽略判断*/IGNORED,/*** 非NULL判断*/NOT_NULL,/*** 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)*/NOT_EMPTY,/*** 默认的,一般只用于注解里* <p>1. 在全局里代表 NOT_NULL</p>* <p>2. 在注解里代表 跟随全局</p>*/DEFAULT,/*** 不加入 SQL*/NEVER
}

FieldFill

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

在数据表的设计中,经常需要加一些字段,如:创建时间,最后修改时间等。

  • 一种是在数据库中设置创建时间的默认值为CURRENT_TIMESTAMP,更新时间勾选根据当前时间戳更新
  • 现在可以使用mybatisplus提供的字段填充功能来实现了
UserEntity
@Data
@TableName(value = "`user`")
public class User {@TableId(type = IdType.AUTO)private Integer id;@TableField(value = "nickname")private String nickname;@TableField(value = "is_v")private Integer isV;@TableField(value = "avatar_url")private String avatarUrl;@TableField(value = "create_time",fill = FieldFill.INSERT)private Date createTime;@TableField(value = "update_time",fill = FieldFill.UPDATE)private Date updateTime;}
定义MetaObjectHandler
@Bean
public MetaObjectHandler metaObjectHandler() {return new MetaObjectHandler() {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", Date.class, new Date());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());}};}
使用

// 插入数据,自动设置create_time (这里全部为null,因此只会插入create_time字段)
userService.save(new UserEntity());// 相当于调用userService(null, updateWrapper); 这种情况不会自动设置updateTime
userService.update(new UpdateWrapper<UserEntity>().lambda().eq(UserEntity::getNickname,"zzhua").set(UserEntity::getAvatarUrl,"uuurrrlll"));// 更新数据, 自动设置updateTime
userService.update(new User(), new UpdateWrapper<User>().lambda().eq(User::getNickname, "zzhua").set(User::getAvatarUrl, "uuurrrlll"));
注意事项
  • 填充原理是直接给entity的属性设置值!!!
  • 注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
  • MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充(也就是,如果我们设置了的话,那自动填充不会干涉到我们的操作,)
  • 字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
  • 填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component或@Bean注入
  • 要想根据注解FieldFill.xxx和字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法
  • 不需要根据任何来区分可以使用父类的fillStrategy方法
  • update(T t,Wrapper updateWrapper)时t不能为空,否则自动填充失效

这篇关于Mybatisplus生成代码配置 p6spy打印sql mybatis日志打印 mybatisplus用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/272837

相关文章

SpringBoot集成P6Spy的实现示例

《SpringBoot集成P6Spy的实现示例》本文主要介绍了SpringBoot集成P6Spy的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录本节目标P6Spy简介抛出问题集成P6Spy1. SpringBoot三板斧之加入依赖2. 修改

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

Go语言使用net/http构建一个RESTful API的示例代码

《Go语言使用net/http构建一个RESTfulAPI的示例代码》Go的标准库net/http提供了构建Web服务所需的强大功能,虽然众多第三方框架(如Gin、Echo)已经封装了很多功能,但... 目录引言一、什么是 RESTful API?二、实战目标:用户信息管理 API三、代码实现1. 用户数据

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热

Conda国内镜像源及配置过程

《Conda国内镜像源及配置过程》文章介绍Conda镜像源使用方法,涵盖临时指定单个/多个源、永久配置及恢复默认设置,同时说明main(官方稳定)、free(逐渐弃用)、conda-forge(社区更... 目录一、Conda国内镜像源二、Conda临时使用镜像源指定单个源临时指定多个源创建环境时临时指定源

MySQL 临时表创建与使用详细说明

《MySQL临时表创建与使用详细说明》MySQL临时表是存储在内存或磁盘的临时数据表,会话结束时自动销毁,适合存储中间计算结果或临时数据集,其名称以#开头(如#TempTable),本文给大家介绍M... 目录mysql 临时表详细说明1.定义2.核心特性3.创建与使用4.典型应用场景5.生命周期管理6.注

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

mybatisplus的逻辑删除过程

《mybatisplus的逻辑删除过程》:本文主要介绍mybatisplus的逻辑删除过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录myBATisplus的逻辑删除1、在配置文件中添加逻辑删除的字段2、在实体类上加上@TableLogic3、业务层正常删除即

MySQL磁盘空间不足问题解决

《MySQL磁盘空间不足问题解决》本文介绍查看空间使用情况的方式,以及各种空间问题的原因和解决方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录查看空间使用情况Binlog日志文件占用过多表上的索引太多导致空间不足大字段导致空间不足表空间碎片太多导致空间不足临时表空间