Mybatis Plus—数据安全保护、批量操作

news/2024/7/24 1:43:11 标签: mybatis

一、数据安全保护 

该功能为了保护数据库配置及数据安全,在一定的程度上控制开发人员流动导致敏感信息泄露。

  • 3.3.2 开始支持
  • 配置安全

YML 配置:

// 加密配置 mpw: 开头紧接加密内容( 非数据库配置专用 YML 中其它配置也是可以使用的 )
spring:
  datasource:
    url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6Bf1oEMZ1gVpPPhdDmjQqoM
    password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
    username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==

密钥加密:

// 生成 16 位随机 AES 密钥
String randomKey = AES.generateRandomKey();

// 随机密钥加密
String result = AES.encrypt(data, randomKey);

如何使用:

// Jar 启动参数( idea 设置 Program arguments , 服务器可以设置为启动环境变量 )
--mpw.key=d1104d7c3b616f0b
  • 数据安全:

👉 字段加密解密(opens new window)

👉 字段脱敏(opens new window)

  • SQL 注入安全保护说明
Wrappers.query()
// 开启自动检查 SQL 注入
.checkSqlInjection().orderByDesc("任意前端传入字段")
​
// 手动校验方式
SqlInjectionUtils.check("任意前端传入字段")

注意!

  • 加密配置必须以 mpw: 字符串开头
  • 随机密钥请负责人妥善保管,当然越少人知道越好。

二、批量操作

  • 3.5.4 + 版本支持
  • 事务需要手动自行控制(默认false)
  • 注意
  • autoCommit参数在Spring项目下是无效的,具体见SpringManagedTransactionFactory,在原生mybatis下可用
  • 执行返回值为批量处理结果,业务可根据返回值判断是否成功
  • 数据能否写入或更新取决于代码能否正确执行到flushStatements
  • 支持Spring与非Spring项目使用
  • 执行抛出异常为PersistenceException
  • saveOrUpdate是个比较有争议的方法,个人建议批量操作保持为简单的新增或更新操作

1、类说明

   1.1 MybatisBatch<?>

  • 泛型为具体 实际数据类型
  • sqlSessionFactory可通过容器获取,非Spring容器下可在自行初始化Mybatis时将上下文记录起来
  • dataList为实际的批量数据处理 (非空)

 1.2 MybatisBatch.Method<?>

实际为BatchMethod, 封装了框架内部操作方法简化调用.

  • 泛型为 实际Mapper方法参数需要的类型
  • mapperClass为具体的实际Mapper类

#BatchMethod<?>

  • 泛型为 实际Mapper方法参数需要的类型
  • statementId : 执行的MappedStatement
  • parameterConvert: 参数类型转换处理器,当数据类型与实际mapper方法参数不一致时,可以通过类型转换器进行转换

2、使用说明

  1. 构建MybatisBatch (将数据与sqlSessionFactory绑定起来)
  2. 构建MybatisBatch.Method (确定执行执行Mapper类方法)
  3. 执行操作 (执行处理操作,将批量参数转换为实际mapper需要的参数)

3、返回值说明

List<BatchResult>

执行返回每次按照执行MappedStatement + sql分组返回的操作结果

注意

例如批量根据id更新:

假设10条数据, 5条更新一个字段 5条更新两个字段 , 那返回值就是容量为2的List, 里面各存储了五条记录更新情况

update table set c1 = ? where id = ? //只更新一个字段

update table set c1 = ? , c2 = ? where id = ? // 只更新两个字段

mappedStatement: 执行的MappedStatement

sql: 执行sql

parameterObjects: 参数列表

updateCounts[]: 影响行数(与上面的parameterObjects数据一一对应)

4、使用示例

框架提供了一个MybatisBatchUtils进行静态方法调用.

   4.1 execute

适用于insert,update,delete操作

  示例一: 数据类型为实体

List<H2User> userList = Arrays.asList(new H2User(2000L, "测试"), new H2User(2001L, "测试"));
MybatisBatch<H2User> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, userList);
MybatisBatch.Method<H2User> method = new MybatisBatch.Method<>(H2UserMapper.class);
mybatisBatch.execute(method.insert());

示例二: 数据类型为非实体

List<Long> ids = Arrays.asList(120000L, 120001L);
MybatisBatch<Long> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, ids);
MybatisBatch.Method<H2User> method = new MybatisBatch.Method<>(H2UserMapper.class);
mybatisBatch.execute(method.insert(id -> {
    // 将id转换为实体
	H2User h2User = new H2User();
	h2User.setTestId(id);
	return h2User;
}));

示例三: 自定义方法插入(无注解)

// mapper方法(方法参数无注解)
@Insert(
  "insert into h2user(name,version) values( #{name}, #{version})"
)
int myInsertWithoutParam(H2User user1);

// 准备数据集合
List<H2User> h2UserList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
	h2UserList.add(new H2User("myInsertWithoutParam" + i));
}

MybatisBatch<H2User> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, h2UserList);
MybatisBatch.Method<H2User> method = new MybatisBatch.Method<>(H2UserMapper.class);
mybatisBatch.execute(method.get("myInsertWithoutParam"));

示例四: 自定义方法插入(注解)

// 方法参数带注解
@Insert(
  "insert into h2user(name,version) values( #{user1.name}, #{user1.version})"
)
int myInsertWithParam(@Param("user1") H2User user1);

// 准备数据集合
List<H2User> h2UserList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
	h2UserList.add(new H2User("myInsertWithParam" + i));
}

MybatisBatch<H2User> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, h2UserList);
MybatisBatch.Method<H2User> method = new MybatisBatch.Method<>(H2UserMapper.class);
mybatisBatch.execute(method.get("myInsertWithParam", (user) -> {
    // 转换成mapper方法参数
     Map<String, Object> map = new HashMap<>();
     map.put("user1", user);
     return map;
}));

 4.2 saveOrUpdate

执行保存或更新

注意

重点注意跨sqlSession下缓存和数据感知问题

saveOrUpdate(BatchMethod<T> insertMethod, BiPredicate<BatchSqlSession, T> insertPredicate, BatchMethod<T> updateMethod)

  • insertMethod: 指定insert操作处理
  • insertPredicate: 指定insert操作处理条件

注意

注意这里的BatchSqlSession,使用这个进行查询操作会每次都执行一次flushStatements.

如果在一次处理中,如果有两条记录相同的数据,在跨sqlSession中会执行两次插入导致主键冲突,而共享sqlsesion下会执行一次插入和一次更新

  • updateMethod: 指定update操作处理

 跨sqlSession

@Autowired
private H2UserMapper userMapper;

List<H2User> h2UserList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    h2UserList.add(new H2User(Long.valueOf(40000 + i), "test" + i));
}
MybatisBatch.Method<H2User> mapperMethod = new MybatisBatch.Method<>(H2UserMapper.class);

new MybatisBatch<>(sqlSessionFactory,h2UserList).saveOrUpdate(
            mapperMethod.insert(), // 指定insert方法
            ((sqlSession, h2User) -> userMapper.selectById(h2User.getTestId()) == null),  //判断条件,引用另个mapper方法
            mapperMethod.updateById()); // 指定update方法

 共用sqlSession

List<H2User> h2UserList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    h2UserList.add(new H2User(Long.valueOf(50000 + i), "test" + i));
}
MybatisBatch.Method<H2User> mapperMethod = new MybatisBatch.Method<>(H2UserMapper.class);

new MybatisBatch<>(sqlSessionFactory,h2UserList).saveOrUpdate(mapperMethod.insert(), // 指定insert方法
            ((sqlSession, h2User) -> sqlSession.selectList(mapperMethod.get("selectById").getStatementId(), h2User.getTestId()).isEmpty()), //判断条件,共用sqlSession
            mapperMethod.updateById()); // 指定update方法

 4.3 事务处理

   Spring事务处理示例一

@Autowired
private TransactionTemplate transactionTemplate;

transactionTemplate.execute((TransactionCallback<List<BatchResult>>) status -> {
    MybatisBatch.Method<H2User> mapperMethod = new MybatisBatch.Method<>(H2UserMapper.class);
        // 执行批量插入
    MybatisBatchUtils.execute(sqlSessionFactory, h2UserList, mapperMethod.insert());
    throw new RuntimeException("出错了");
});


http://www.niftyadmin.cn/n/5203657.html

相关文章

万字解析:十大排序(直接插入排序+希尔排序+选择排序+堆排序+冒泡排序+快速排序+归并排序+计数排序+基数排序+桶排序)

文章目录 十大排序排序算法复杂度及稳定性分析一、 排序的概念1.排序&#xff1a;2.稳定性&#xff1a;3.内部排序&#xff1a;4.外部排序&#xff1a; 二、插入排序1.直接插入排序2.希尔排序 三、选择排序1.直接选择排序方法一方法二直接插入排序和直接排序的区别 2.堆排序 四…

三十分钟学会Linux的基本操作

GNU/Linux GNU项目是由Richard Stallman发起的自由软件运动&#xff0c;旨在创建一个完全自由的操作系统。虽然GNU项目已经开发了大量的系统组件和工具&#xff0c;但它一直缺少一个完整的操作系统内核。在这时Linus Torvalds开发了Linux内核&#xff0c;并将其发布为自由软件…

opencv-python读取的图像分辨率太大不能完全显示

如果使用OpenCV-Python读取的图像分辨率太大&#xff0c;无法完全显示在屏幕上&#xff0c;可以考虑以下几种方法&#xff1a; 1.缩放图像&#xff1a;使用OpenCV的resize函数&#xff0c;将图像缩小到适合屏幕显示的大小。例如&#xff0c;可以将图像的宽度和高度都缩小到屏幕…

VMware 系列:vmware vsphere虚拟化简介以及产品系下载、Esxi安装

vmware vsphere虚拟化简介以及产品系下载、Esxi安装 一. vmware vsphere 虚拟化(1.1)为什么要学习虚拟化(1.2)虚拟化产品介绍(1.3)Vsphere6.7特性二. ESXI(2.0)如何知道哪些品牌对应支持哪些版本的 ESXI,ESXI各个版本对OS的支持又是什么?比如看看哪些机器支持哪些版本…

使用sed命令进行文本处理示例

文章目录 前言查找并替换操作在文件中添加文本删除文件中的文本高亮显示文件中的文本 转载请标明出处&#xff1a; https://bigmaning.blog.csdn.net/article/details/134539923 本文出自:【BigManing的博客】 前言 当我们需要在Linux系统中处理文本文件时&#xff0c;经常需要…

评分105分获批者过来人告诉你,香港优才计划申请还是不能太老实了!

评分105分获批者过来人告诉你&#xff0c;香港优才计划申请还是不能太老实了&#xff01; 申请香港优才计划虽然看起来很简单&#xff0c;但是其中的流程也挺繁琐、复杂。若是自己条件足够优秀&#xff0c;而且自己有足够的时间和精力的话&#xff0c;DIY申请也可以的。需要自己…

【20年扬大真题】编写程序,功能是从键盘输入若干4位数字学号,然后输出学号中百位数字是3的学号 (输入0时结束循环)

【20年扬大真题】 编写程序&#xff0c;功能是从键盘输入若干4位数字学号&#xff0c;然后输出学号中百位数字是3的学号 &#xff08;输入0时结束循环&#xff09; #include<stdio.h> #define MaxSize 20 int BaiWei3(int x) {x x / 100;if (x % 10 3) {return 1;}els…

CuratorFrameworkFactory.builder()方法可配置属性

CuratorFrameworkFactory.builder()方法可以配置以下属性&#xff1a; 1. connectString&#xff1a;ZooKeeper服务器的连接字符串。 2. sessionTimeoutMs&#xff1a;ZooKeeper会话超时时间。 3. connectionTimeoutMs&#xff1a;ZooKeeper连接超时时间。 4. retryPolicy&…