作用:
-
提供16位雪花ID实现,解决默认19位实现导致的前端精度问题
-
数据初始化时默认填充,insert时,自动获取cnaworld.mybatis-plus.fill-strategy-field 中的属性进行填充
-
默认开启乐观锁实现 OptimisticLockerInnerInterceptor
-
扩展逻辑删除相关方法,提供逻辑恢复和直接删除扩展方法
-
默认开启CRUD字段自动加密解密
-
客户端配置
<dependency> <groupId>cn.cnaworld.framework</groupId> <artifactId>mybatis-plus</artifactId> <version>{latest}</version> </dependency>
-
application.yml 配置
cnaworld: mybatis-plus: enabled: true #总开关,关闭后同时关闭所有增强功能,默认true开启, auto-field-encrypt: true #使用对象进行CRUD时,若字段上存在@CnaFieldEncrypt注解则会自动加密解密 auto-insert-fill: true #数据初始化时默认填充,insert时,自动获取fill-strategy-field 中的属性进行填充。 function-extension: true #扩展逻辑删除相关方法,提供逻辑恢复和直接删除扩展方法。默认true开启。 snow-flake: true #提供16位雪花ID实现。默认true开启。 optimistic-locker: true #提供乐观锁实现 OptimisticLockerInnerInterceptor。默认true开启。 fill-strategy-field: #数据初始化时默认填充属性集合 - field-name: "createTimeDb" #需填充的entity字段名称,需要注解 @TableField(value = "create_time_db",fill = FieldFill.INSERT) 中开启fill = FieldFill.INSERT field-class: java.time.LocalDateTime #默认填充字段类型,Date 、Timestamp 、 LocalDateTime 默认取当前时间,Long 、Integer 默认取0。 - field-name: "updateTimeDb" field-processor-class: cn.cnaworld.cnaworldaoptest.api.AutoInsertFillProcessor #填充值处理器,实现FieldProcessor的getFieldValue方法,返回值作为属性填充值。 - field-name: "deletedDb" field-value: false #填充值 field-encrypt: #使用对象进行CRUD时,若字段上存在@CnaFieldEncrypt注解则会自动加密解密 algorithm: aes #String 类型字段加密算法 keys: Ssadasa123dsfsda21sdasd #加密密钥 encrypt-algorithm-processor: cn.cnaworld.framework.infrastructure.component.mybatisplus.processor.stringprocessor.impl.AESEncryptProcessor #自定义实现处理器
-
具体使用
-
16位雪花ID使用方式
-
//entity 主键注解type 采用IdType.ASSIGN_ID @TableId(value = "student_id", type = IdType.ASSIGN_ID) private Long studentId;
-
-
数据初始化时默认填充使用方式
- cnaworld.mybatis-plus.fill-strategy-field 添加相关配置 , 需填充的entity字段名称 field-name 必须填写,field-value 、field-processor-class、field-class 任选其一。若全部配置优先级为 :field-value > field-processor-class > field-class
- field-value 类型为 Object ,可直接配置字段值 ,若和 field-name 的实际类型不匹配则无法进行此值的填充 ,但不会影响其他值的填充
- field-processor-class 可配置实现了FieldProcessor接口getFieldValue方法的类的全限定名称,此接口支持客户端进行逻辑处理将结果提供给字段进行填充。getFieldValue方法返回值为 Object若和 field-name 的实际类型不匹配则无法进行此值的填充 ,但不会影响其他值的填充
- field-class 支持的类型为:Date 、Timestamp 、 LocalDateTime 默认取当前时间,Long 、Integer 默认取0
- 需要entity字段注解中开启 fill = FieldFill.INSERT 如: @TableField(value = "deleted_db",fill = FieldFill.INSERT)
- cnaworld.mybatis-plus.fill-strategy-field 添加相关配置 , 需填充的entity字段名称 field-name 必须填写,field-value 、field-processor-class、field-class 任选其一。若全部配置优先级为 :field-value > field-processor-class > field-class
-
乐观锁实现使用方式
-
乐观锁采用官网推荐的OptimisticLockerInnerInterceptor(true) , 且开启了wrapperMode 模块。
-
需要entity字段添加@Version注解
-
mybatis-plus对自定义方法、逻辑删除方法更新时无法对数据乐观锁字段进行更新问题,建议使用updateTimeDb作为乐观锁字段,并在数据库层面设置根据当前时间戳更新。mysql 5.6以上支持,PG可使用触发器支持。
-
@Version private LocalDateTime updateTimeDb;
-
-
使用对象进行CRUD时,若字段上存在**@CnaFieldEncrypt**注解则会自动加密解密
1、支持的类型有:String、byte、short、int、long、float、double、BigDecimal、boolean、Date、LocalDate、LocalDateTime。
2、配置文件配置为全局配置,注解中的配置为独立配置。
3、可使用 auto-field-encrypt 配置控制功能是否开启,默认开启。
4、注意:由于算法问题BigDecimal 最少设置11位精度
@CnaFieldEncrypt(keys = {"123"},encryptAlgorithm = EncryptAlgorithm.AES,encryptAlgorithmProcessor = AESEncryptProcessor.class) @TableField("encrypt") private String encrypt; @CnaFieldEncrypt @TableField("encrypt_short") private short encryptShort; @CnaFieldEncrypt @TableField("encrypt_byte") private byte encryptByte; @CnaFieldEncrypt @TableField("encrypt_int") private int encryptInt; @CnaFieldEncrypt @TableField("encrypt_long") private long encryptLong; @CnaFieldEncrypt @TableField("encrypt_double") private double encryptDouble; @CnaFieldEncrypt @TableField("encrypt_float") private float encryptFloat; @CnaFieldEncrypt @TableField("encrypt_big_decimal") private BigDecimal encryptBigDecimal; @CnaFieldEncrypt @TableField("encrypt_boolean") private boolean encryptBoolean; @CnaFieldEncrypt @TableField("encrypt_time") private Date encryptTime; @CnaFieldEncrypt @TableField("encrypt_local_time") private LocalDateTime encryptLocalTime; @TableField("encrypt_local_date") private LocalDate encryptLocalDate;
-
扩展逻辑删除相关方法,提供逻辑恢复和直接删除扩展方法
-
若entity字段增加逻辑删除注解支持,则所有的mybatis-plus提供的Service删除方法及ServiceImpl 的 remove()、delete() , 方法都会开启逻辑删除
-
需要由继承mybatis-plus 的IService、ServiceImpl<TMapper, T>、BaseMapper,改为继承CnaWorldBaseService、CnaWorldBaseServiceImpl<TMapper, T> 、CnaWorldBaseMapper
-
同时提供了CnaWorldBaseEntity 可供使用
- 建议使用updateTimeDb同时作为乐观锁字段
- 建议使用deletedDb同时作为逻辑删除字段
-
CnaWorldBaseService 扩展方法提供逻辑恢复 和 直接删除
//逻辑恢复 default boolean restore(Wrapper<T> queryWrapper) //逻辑恢复 default boolean restoreById(Serializable id) //逻辑恢复 default boolean restoreByMap(Map<String, Object> columnMap) //逻辑恢复 default boolean restoreByIds(Collection<? extends Serializable> idList) //直接删除 default boolean directRemove(Wrapper<T> queryWrapper) //直接删除 default boolean directRemoveById(Serializable id) //直接删除 default boolean directRemoveByMap(Map<String, Object> columnMap) //直接删除 default boolean directRemoveByIds(Collection<? extends Serializable> idList)
-
CnaWorldBaseMapper 扩展方法提供逻辑恢复 和 直接删除
//逻辑恢复 int recover(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); //逻辑恢复 int recoverById(Serializable id); //逻辑恢复 int recoverByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); //逻辑恢复 int recoverBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); //直接删除 int directDelete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); //直接删除 int directDeleteById(Serializable id); //直接删除 int directDeleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); //直接删除 int directDeleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
-
自动生成代码类,可直接配置 superClass 继承扩展实现
package cn.cnaworld.base; import cn.cnaworld.framework.infrastructure.component.mybatisplus.baseclass.entity.CnaworldBaseEntity; import cn.cnaworld.framework.infrastructure.component.mybatisplus.baseclass.mapper.CnaworldBaseMapper; import cn.cnaworld.framework.infrastructure.component.mybatisplus.baseclass.service.CnaworldBaseService; import cn.cnaworld.framework.infrastructure.component.mybatisplus.baseclass.service.impl.CnaWorldBaseServiceImpl; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.builder.GeneratorBuilder; import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert; import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler; public class CnaworldBaseCodeGenerator { public static void main(String[] args) { DataSourceConfig mysqlDataSourceConfig = new DataSourceConfig.Builder( "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useSSL=false&characterEncoding=utf8","root","root") .typeConvert(new MySqlTypeConvert()) .keyWordsHandler(new MySqlKeyWordsHandler()) .dbQuery(new MySqlQuery()) .build(); GlobalConfig globalConfig = GeneratorBuilder.globalConfigBuilder() .fileOverride()//是否覆盖已生成文件 默认值:false .openDir(false)//是否打开生成目录 默认值:true .outputDir("./src/main/java/")//指定输出目录 默认值: windows:D:// linux or mac : /tmp .author("Lucifer")//作者名 默认值:无 //.enableKotlin()//是否生成kotlin 默认值:false .enableSwagger()//是否生成swagger注解 默认值:false .dateType(DateType.TIME_PACK)//时间策略 默认值: DateType.TIME_PACK .commentDate("yyyy-MM-dd")//注释日期 默认值: yyyy-MM-dd .build(); PackageConfig packageConfig = new PackageConfig.Builder() .parent("cn.cnaworld.base.infrastructure.repository.book") //父包名 默认值:com.baomidou .moduleName("orm") //父包模块名 默认值:无 .entity("po") //Entity包名 默认值:entity .service("service") //Service包名 默认值:service .serviceImpl("service.impl") //Service Impl包名 默认值:service.impl .mapper("mapper") //Mapper包名 默认值:mapper .xml("mapper.xml") //Mapper XML包名 默认值:mapper.xml //.controller("controller") //Controller包名 默认值:controller .build(); TemplateConfig templateConfig = new TemplateConfig.Builder().build(); // 激活所有默认模板 //LikeTable likeTable=new LikeTable("operate_log"); StrategyConfig strategyConfig = new StrategyConfig.Builder() .enableCapitalMode()//开启大写命名 //.enableSkipView()//开启跳过视图 //.disableSqlFilter()//禁用sql过滤 //.likeTable(likeTable)//模糊表匹配(sql过滤) //.notLikeTable(null)//模糊表匹配(sql过滤) //.addFieldPrefix("")//增加表字段前缀 .addInclude("book")//增加表匹配(内存过滤) //.addInclude("goods")//增加表匹配(内存过滤) //.addInclude("email_account_manage")//增加表匹配(内存过滤) //.addExclude("")//增加表排除匹配(内存过滤) //.addTablePrefix("")//增加表前缀 //实体策略配置 .entityBuilder()//实体策略配置 .superClass(CnaworldBaseEntity.class)//父类W //.enableColumnConstant()//开启生成字段常量W //.enableChainModel()//开启链式模型 //.addSuperEntityColumns("")//添加父类公共字段 //.addTableFills(new Column(null),new Column(null))//添加属性填充字段 //.enableActiveRecord()//开启ActiveRecord模型 //.convertFileName(null)//转换文件名称 //.formatFileName(null)//格式化文件名称 //.enableSerialVersionUID()//开启生成serialVersionUID .enableLombok()//开启lombok模型 .addIgnoreColumns("deleted_db","create_by_db","update_by_db","create_time_db","update_time_db") .enableRemoveIsPrefix()//开启Boolean类型字段移除is前缀 .enableTableFieldAnnotation()//开启生成实体时生成字段注解 .versionColumnName("update_time_db")//乐观锁字段名(数据库) .versionPropertyName("updateTimeDb")//乐观锁属性名(实体) .logicDeleteColumnName("deleted_db")//逻辑删除字段名(数据库) .logicDeletePropertyName("deleteDB")//逻辑删除属性名(实体) .naming(NamingStrategy.underline_to_camel)//数据库表映射到实体的命名策略 默认:NamingStrategy.no_change .columnNaming(NamingStrategy.underline_to_camel)//数据库表字段映射到实体的命名策略 .idType(IdType.ASSIGN_ID)//全局主键类型 //controller策略配置 .controllerBuilder()//controller策略配置 //.superClass(CodeGenerator.class)//父类 //.convertFileName(null)//转换文件名称 //.formatFileName("")//格式化文件名称 .enableHyphenStyle()//开启驼峰转连字符 .enableRestStyle()//开启生成@RestController控制器 //service策略配置 .serviceBuilder()//service策略配置 .superServiceClass(CnaworldBaseService.class)//设置service接口父类 .superServiceImplClass(CnaWorldBaseServiceImpl.class)//设置service实现类父类 //.convertServiceFileName(null)//转换service接口文件名称 //.convertServiceImplFileName(null)//转换service实现类文件名称 //.formatServiceFileName(null)//格式化service接口文件名称 //.formatServiceImplFileName(null)//格式化service实现类文件名称 //mapperBuilder .mapperBuilder()//mapperBuilder .superClass(CnaworldBaseMapper.class)//设置父类 //.cache(null)//设置缓存实现类 //.formatMapperFileName("")//格式化mapper文件名称 //.formatXmlFileName("")//格式化xml实现类文件名称 //.convertMapperFileName(null)//转换mapper类文件名称 //.convertXmlFileName(null)//转换xml文件名称 .enableBaseResultMap()//启用BaseResultMap生成 .enableBaseColumnList()//启用BaseColumnList .build(); strategyConfig.entityBuilder().nameConvert(new INameConvertCust(strategyConfig)); InjectionConfig injectionConfig = new InjectionConfig.Builder().build(); // 代码生成器 new AutoGenerator(mysqlDataSourceConfig).global(globalConfig).packageInfo(packageConfig) .strategy(strategyConfig) .template(templateConfig) .injection(injectionConfig) .execute(); } }
-
-
-
客户端中也加入此基础Entity类 , 放到客户端方便切换openapi 2.0、3.0 ,mybatisplus.generator 提供的模板默认是2.0的故,此类也默认采用2.0的实现。可采用自定义模板的方式调整为3.0实现。
package cn.cnaworld.framework.infrastructure.component.mybatisplus.baseclass.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 基本实体类
* @author Lucifer
* @date 2023/3/5
* @since 1.0.0
*/
@Getter
@Setter
@ToString
@Schema(name = "CnaWorldBaseEntity对象")
public class CnaworldBaseEntity implements Serializable {
/**
* 逻辑删除
*/
@Schema(description = "逻辑删除")
@TableField(value = "deleted_db",fill = FieldFill.INSERT)
@TableLogic
private Boolean deletedDb;
/**
* 创建者
*/
@Schema(description = "创建者")
@TableField("create_by_db")
private String createByDb;
/**
* 更新者
*/
@Schema(description = "更新者")
@TableField("update_by_db")
private String updateByDb;
/**
* 创建日期
*/
@Schema(description = "创建日期")
@TableField(value = "create_time_db",fill = FieldFill.INSERT)
private LocalDateTime createTimeDb;
/**
* 更新日期
*/
@Schema(description = "更新日期")
@TableField(value = "update_time_db",fill = FieldFill.INSERT)
@Version
private LocalDateTime updateTimeDb;
}
启动时,会打印开启的组件的注册日志。
2023-03-07 23:24:31.263 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus optimistic-locker initialized !
2023-03-07 23:24:31.265 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus update-optimistic-locker-field initialized !
2023-03-07 23:24:31.286 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus auto-insert-fill initialized !
2023-03-07 23:24:31.300 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus extend method initialized !
2023-03-07 23:24:31.304 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus 16-snowflake initialized !
2023-08-17 14:35:59.824 INFO 49200 --- [ main] c.c.f.i.c.m.config.MybatisPlusConfig : cnaworld mybatis-plus auto-field-encrypt initialized !
- 客户端应用demo 应用demo