MybatisPlus
概述
介绍
官网:https://mp.baomidou.com/
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
框架结构
简单使用
导入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
注意:
- mybatis-plus-boot-starter 3.x以上版本需要mysql驱动:com.mysql.cj.jdbc.Driver,可以不指明mysql版本,默认下载最新
- 不要同时导入mybatis和mybatis plus ,会有版本差异
实体类
@Data
public class Student {
private int id;
private String name;
private int age;
}
mapper接口
@Repository//识别为资源
//继承BaseMapper,指定泛型为数据类型
public interface StudentDao extends BaseMapper<Student> {
}
启动类
@SpringBootApplication
@MapperScan("com.lyne.dao")//扫描mapper包
public class MybatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusDemoApplication.class, args);
}
}
配置文件
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis?userUnicode=true&useSSL=false&serverTimezone=GMT
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: 123456
tomcat:
test-while-idle: false
driver-class-name: com.mysql.cj.jdbc.Driver
测试
@Test
void contextLoads() {
List<Student> students = studentDao.selectList(null);
System.out.println(students);
Student student = studentDao.selectById(1);
System.out.println(student);
}
常用注解
@TableName 表名注解
参数
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 表名 |
schema | String | 否 | "" | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
resultMap | String | 否 | "" | xml 中 resultMap 的 id |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名(@since 3.3.1) |
@TableId 主键注解 标注在实体类主键上
参数
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
IdType类型
值 | 描述 |
---|---|
AUTO | 数据库ID自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert前自行set主键值 |
ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator ——雪花算法) |
ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认default方法) |
ID_WORKER | 分布式全局唯一ID 长整型类型(please use ASSIGN_ID ) |
UUID | 32位UUID字符串(please use ASSIGN_UUID ) |
ID_WORKER_STR | 分布式全局唯一ID 字符串类型(please use ASSIGN_ID ) |
@TableField 字段注解(非主键) 用于自动填充数据如创建修改时间 标注在日期类型上
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 数据库字段名 |
el | String | 否 | "" | 映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | "" | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} ,参考(opens new window) |
update | String | 否 | "" | 字段 update set 部分注入, 例如:update="%s+1":表示更新时会set version=version+1(该属性优先级高于 el 属性) |
insertStrategy | Enum | N | DEFAULT | 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | N | DEFAULT | 举例:IGNORED: update table_a set column=#{columnProperty} |
whereStrategy | Enum | N | DEFAULT | 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | "" | 指定小数点后保留的位数 |
FieldStrategy
值 | 描述 |
---|---|
IGNORED | 忽略判断 |
NOT_NULL | 非NULL判断 |
NOT_EMPTY | 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断) |
DEFAULT | 追随全局配置 |
FieldFill <常用>
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
实体类标注
@TableField(fill = FieldFill.INSERT)//插入时填充
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) //插入更新时填充
private Date updateTime;
使用自动填充需要实现接口: MyMetaObjectHandler
@Slf4j //日志记录
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时操作
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
// 或者
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
//更新时操作
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
// 或者
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
}
@Version 乐观锁注解 标注在实体类的属性上,指定为版本
需要加入配置信息
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
@EnumValue: 实体属性使用枚举类型 标记在枚举类属性上
注解标记类型
public enum GradeEnum {
PRIMARY(1, "小学"), SECONDORY(2, "中学"), HIGH(3, "高中");
GradeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
@EnumValue//标记数据库存的值是code
private final int code;
//。。。
}
扫描枚举包
mybatis-plus:
# 支持统配符 * 或者 ; 分割
typeEnumsPackage: com.baomidou.springboot.entity.enums
....
实体类中直接使用
private GradeEnum grade;
若需要序列化
Jackson
-
重写toString方法
添加配置
@Bean public Jackson2ObjectMapperBuilderCustomizer customizer(){ return builder -> builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); }
然后在枚举中复写toString方法即可.
-
添加
@JsonValue
注解public enum GradeEnum { PRIMARY(1, "小学"), SECONDORY(2, "中学"), HIGH(3, "高中"); GradeEnum(int code, String descp) { this.code = code; this.descp = descp; } @EnumValue @JsonValue //标记响应json值 private final int code; }
Fastjson
-
添加配置
全局处理方式
FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);
局部处理方式
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString) private UserStatus status;
-
枚举中复写toString方法
@TableLogic:实现逻辑删除,标记在逻辑判断字段上
@TableLogic
private Integer deleted;
需要修改配置文件
mybatis-plus:
global-config:
db-config:
logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
@KeySequence 序列主键策略 oracle
- 参数:value、resultMap
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 序列名 |
clazz | Class | 否 | Long.class | id的类型, 可以指定String.class,这样返回的Sequence值是字符串"1" |
@OrderBy 内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
isDesc | boolean | 否 | 是 | 是否倒序查询 |
sort | short | 否 | Short.MAX_VALUE | 数字越小越靠前 |
配置日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出
CURD
添加
@Test
void test01() {
Student student = new Student();
student.setName("a");
student.setAge(11);
studentDao.insert(student);
}
-
当主键为int类型时,ID值默认自增
-
当主键为Long类型时,mybatisplus提供默认使用
雪花算法
生成ID此时,可以在实体类中加入注解并对ID的生成类型设置
@Data public class Student { //默认为 IdType.ASSIGN_ID @TableId(type = IdType.ASSIGN_ID) private Long id; private String name; private int age; }
也可以通过配置文件设置主键自增策略 但仍然需要
@TableId
指明主键mybatis-plus: global-config: db-config: id-type: ASSIGN_ID //主键自动生成
修改
@Test
void updateTest(){
Student student = studentDao.selectById(1430115359345127425L);
student.setName("abc");
//方式一 根据 ID 选择修改
studentDao.updateById(student);
//方式二 根据 UpdateWrapper 条件,更新记录 updateWrapper可为null entity 用于生成 where 语句
studentDao.update(student,new UpdateWrapper<>());
}
删除
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
实例
@Test
void deleteTest() {
//批量删除
studentDao.deleteBatchIds(Arrays.asList(1,2,3));
}
查询
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
实例
@Test
void contextLoads() {
List<Student> students = studentDao.selectList(null);
System.out.println(students);
Student student = studentDao.selectById(1);
System.out.println(student);
}
条件构造器
实现类
接口: public abstract class Wrapper<T> implements ISqlSegment
抽象基类 public abstract class AbstractWrapper
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
实现类
- QueryWrapper 用于查询条件封装
- UpdateWrapper 用于更新条件封装
- LambdaQueryWrapper Lambda 语法使用 Wrapper
- LambdaUpdateWrapper Lambda 更新封装
此外提供链式操作的实现类
LambdaQueryWrapper解耦了数据库列名与实体属性名,解决了硬编码的问题
方法
参数说明:
- condition 表示该条件判断是否开启,默认为true.
- entity:数据库表映射实体类
常用方法
- allEq() 当传入参数很多的时候,可以直接用map接受参数,然后用map构造条件构造器
- isNotNull() 字段不为空
- isNull() 字段为空
- ge(R column, Object val) 字段大于等于 >= val
- gt(R column, Object val) 大于 >
- le(R column, Object val) 字段小于等于 <= val
- lt(R column, Object val) 小于 <
- between(R column, Object val1, Object val2) 字段值在val1和val2之间
- notBetween(R column, Object val1, Object val2)
- eq(R column, Object val) 等于 =
- ne(R column, Object val) 不等于 <>
- like(R column, Object val) 模糊查询 LIKE '%值%'
- notLike(R column, Object val) NOT LIKE '%值%'
- likeLeft(R column, Object val) LIKE '%值'
- likeRight(R column, Object val) LIKE '值%'
- in(R column, Collection<?> value) 字段 IN (value.get(0), value.get(1), ...) value集合类型
- notIn(R column, Collection<?> value)
- inSql(R column, String inValue)
- e.g: inSql("age", "1,2,3,4,5,6")
- e.g: inSql("id", "select id from table where id < 3")
- groupBy(R... columns) 分组
- orderBy(boolean condition, boolean isAsc, R... columns) 排序
- func(Consumer
consumer) func 方法(主要方便在出现if...else下调用不同方法能不断链) - 例: func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
- or() 拼接 表示or
- 主动调用
or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接)
- 主动调用
- and(Consumer consumer) and嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))
--->and (name = '李白' and status <> '活着')
- 例:
- apply(String applySql, Object... params) 拼接sql
- 该方法可用于数据库函数 动态入参的
params
对应前面applySql
内部的{index}
部分.这样是不会有sql注入风险的,反之会有!
- 该方法可用于数据库函数 动态入参的
- ......
分页功能
内置分页功能
加入配置文件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
UserServiceImpl.java 调用分页方法
public IPage<User> selectUserPage(Page<User> page, Integer state) {
// 不进行 count sql 优化,解决 MP 无法自动优化 SQL 问题,这时候你需要自己查询 count 部分
// page.setOptimizeCountSql(false);
// 当 total 为小于 0 或者设置 setSearchCount(false) 分页插件不会进行 count 查询
// 要点!! 分页返回的对象与传入的对象是同一个
return userMapper.selectPageVo(page, state);
}
实例
@Test
void pageTest(){
Page<Student> page = new Page<>();
page.setSize(3);//设置每页三条数据
page.setCurrent(1);//默认为1
Page<Student> studentPage = studentDao.selectPage(page, null);//查询第一页
List<Student> records = studentPage.getRecords();//获取数据
records.forEach(System.out::println);
}
性能分析器
代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
注:MyBatis-Plus 从 3.0.3
之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖
导入代码生成器 依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,
用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>latest-velocity-version</version>
</dependency>
如果是选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。
AutoGenerator generator = new AutoGenerator();
// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());
// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());
// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());
// other config
...
配置信息
public static void main(String[] args) {
AutoGenerator autoGenerator = new AutoGenerator();
//1.全局设置
GlobalConfig gc = new GlobalConfig();
String property = System.getProperty("user.dir");
gc.setOutputDir(property + "/src/main/java");//输出目录
gc.setOpen(false);//是否打开资源管理器
gc.setFileOverride(false);//是否覆盖
gc.setAuthor("lyne");//作者信息
gc.setServiceName("%sService");//设置服务接口名字 去掉serviceI前缀
gc.setIdType(IdType.ASSIGN_ID);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
autoGenerator.setGlobalConfig(gc);
//2.数据源设置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis?userUnicode=true&useSSL=false&serverTimezone=GMT");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
autoGenerator.setDataSource(dsc);
//3.包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.lyne");
autoGenerator.setPackageInfo(pc);
//4.策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true); //自动lombok
strategy.setRestControllerStyle(true);
// 写于父类中的公共字段
strategy.setInclude("student");//设置映射的表名
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
TableFill updateTime = new TableFill("update_time", FieldFill.INSERT_UPDATE);
strategy.setTableFillList(Arrays.asList(createTime, updateTime));
strategy.setVersionFieldName("version");//开启乐观锁
strategy.setRestControllerStyle(true);//Restful风格
strategy.setControllerMappingHyphenStyle(true);//驼峰转连字符
autoGenerator.setStrategy(strategy);
autoGenerator.execute();//执行
}
自定义模板
//指定自定义模板路径, 位置:/resources/templates/entity2.java.ftl(或者是.vm)
//注意不要带上.ftl(或者是.vm), 会根据使用的模板引擎自动识别
TemplateConfig templateConfig = new TemplateConfig()
.setEntity("templates/entity2.java");
AutoGenerator mpg = new AutoGenerator();
//配置自定义模板
mpg.setTemplate(templateConfig);
自定义模板引擎: 需要继承类 com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine
数据加密
yml配置使用加密
加密配置 mpw:开头紧接加密内容( 非数据库配置专用 YML 中其它配置也是可以使用的 )
spring:
datasource:
url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6Bf1oEMZ1gVpPPhdDmjQqoM
password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==
密钥生成
// 生成 16 位随机 AES 密钥
String randomKey = AES.generateRandomKey();
// 使用AES密钥进行加密
String result = AES.encrypt(data, randomKey)
使用密钥进行配置文件解密
用于配置文件中IP地址,数据源等信息加密
// Jar 启动参数( idea 设置 Program arguments , 服务器可以设置为启动环境变量 )
--mpw.key=d1104d7c3b616f0b
代码信息加密
用于用户数据加密
//AES加密
@Test
void contextLoads() {
String randomKey = AES.generateRandomKey();
System.out.println("-------加密--------");
System.out.println("AES =====> " + randomKey);
String root = AES.encrypt("root", randomKey);
System.out.println("root ====> " + root);
String url = AES.encrypt("jdbc:mysql://localhost:3306/mybatis?userUnicode=true&useSSL=false&serverTimezone=GMT", randomKey);
System.out.println("url ====> " + url);
System.out.println("-------解密--------");
System.out.println("root ==>" + AES.decrypt(root,randomKey));
System.out.println("url ==>" + AES.decrypt(url,randomKey));
}
注意点
- 加密配置必须以 mpw: 字符串开头
- 随机密钥请负责人妥善保管,当然越少人知道越好