Mybatis-plus更新多张表,保证事务安全的情况下使用异步多线程实现(待验证)

Mybatis-plus更新多张表,保证事务安全的情况下使用异步多线程实现(待验证)

文章目录

  • Mybatis-plus更新多张表,保证事务安全的情况下使用异步多线程实现(待验证)
    • 方案一:
    • 方案二:
    • 方案三:使用mybatis-plus更新数据库的五张不同的表,开启五个线程,每个线程负责更新一张表,如何在保证事务和线程安全的情况下,做到异步更新,编写详细的示例,并详细说明
    • 方案四:
    • 方案五:
    • 方案六:

方案一:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 使用mybatis-plus更新多张表,如何使用异步多线程更新多张表,并且保证事务安全** @author hubin* @since 2018-08-20*/
@Slf4j
public class AsyncUpdateMultiTableExample {public static void main(String[] args) {// 创建线程池ExecutorService executorService = Executors.newFixedThreadPool(10);// 创建service对象IService<User> userService = new UserServiceImpl();// 创建查询条件QueryWrapper<User> queryWrapper = Wrappers.query();queryWrapper.eq("id", 1);// 查询数据List<User> users = userService.list(queryWrapper);// 使用异步多线程更新数据CompletableFuture.allOf(users.stream().map(user -> {return CompletableFuture.runAsync(() -> {// 更新数据userService.updateById(user);}, executorService);}).toArray(CompletableFuture[]::new)).join();// 关闭线程池executorService.shutdown();}/*** 用户表*/public static class User {private Long id;private String name;private Integer age;public Long getId() {return id;}public void setId(Long id) {this.id = id;}}

要使用异步多线程更新多张表并保证事务安全,可以使用Spring框架的异步处理和事务管理功能。下面是一个简单的示例:

  1. 首先,需要在Spring配置文件中启用异步处理和事务管理。可以使用以下配置:
<task:annotation-driven executor="asyncExecutor" /> 
<task:executor id="asyncExecutor" pool-size="10" /> 
<tx:annotation-driven />
  1. 在Java代码中,可以使用@Async注解将方法标记为异步方法。在异步方法中,可以使用@Transactional注解来启用事务管理。例如:
@Service 
public class MyService { @Autowired private MyMapper1 myMapper1; @Autowired private MyMapper2 myMapper2; @Async @Transactional public void updateMultipleTables() { // 更新第一个表 myMapper1.updateTable1(); // 更新第二个表 myMapper2.updateTable2(); // 如果有其他需要更新的表,可以继续添加相应的代码 } 
}
  1. 在调用异步方法时,可以使用Spring的AsyncTaskExecutor来执行异步任务。例如:
@Service 
public class MyOtherService { @Autowired private MyService myService; @Autowired private AsyncTaskExecutor asyncTaskExecutor; public void doUpdate() { // 异步执行多个表的更新操作 asyncTaskExecutor.submit(() -> myService.updateMultipleTables()).get(); } 
}

在上面的代码中,submit()方法将异步任务提交给asyncTaskExecutor执行,get()方法等待异步任务完成。由于异步任务使用了@Transactional注解,因此在异步任务中的所有数据库操作都将在一个事务中执行,保证了事务的完整性和一致性。

需要注意的是,异步任务的执行可能会影响系统的性能和稳定性。因此,需要根据具体的情况进行评估和优化。

方案二:

在使用mybatis-plus更新多张表时,可以使用异步多线程的方式来提高效率。以下是一个简单的实例,演示如何使用异步多线程更新多张表,并确保事务安全。

示例代码:

@Service
public class UpdateService {@Autowiredprivate AsyncService asyncService;@Autowiredprivate TransactionTemplate transactionTemplate;public void updateMultipleTables(UpdateRequest request) {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {asyncService.updateTableA(request.getTableAData());asyncService.updateTableB(request.getTableBData());asyncService.updateTableC(request.getTableCData());}});}
}@Service
public class AsyncService {@Autowiredprivate TableAService tableAService;@Autowiredprivate TableBService tableBService;@Autowiredprivate TableCService tableCService;@Asyncpublic void updateTableA(TableAData data) {tableAService.update(data);}@Asyncpublic void updateTableB(TableBData data) {tableBService.update(data);}@Asyncpublic void updateTableC(TableCData data) {tableCService.update(data);}
}

在上面的代码中,UpdateService 是一个服务类,用于协调多个异步更新操作,并确保它们在同一事务中执行。AsyncService 是一个异步服务类,用于实际执行每个异步更新操作。

UpdateService 中,使用 TransactionTemplate 来启用事务,并在事务中调用异步服务类中的更新方法。由于更新方法被标记为异步,因此它们将在一个独立的线程中执行。

AsyncService 中,每个更新方法都被标记为异步,并且使用相应的服务类来执行实际的更新操作。

注意,@Async 标注了每个更新方法,这意味着每个更新操作将在独立的线程中执行。因此,我们需要确保每个更新方法都是线程安全的,并且能够在多个线程之间正确地共享数据。

总之,使用异步多线程更新多张表可以提高系统的并发处理能力和效率。而使用事务模板可以确保多个更新操作在同一个事务中执行,从而保证了事务安全。 ```

方案三:使用mybatis-plus更新数据库的五张不同的表,开启五个线程,每个线程负责更新一张表,如何在保证事务和线程安全的情况下,做到异步更新,编写详细的示例,并详细说明

在使用多线程更新多张表时,需要注意以下几个方面:

  1. 保证事务安全:多个线程操作多张表需要保证事务的一致性,即要么所有表的更新操作都成功,要么所有表的更新操作都失败。因此,在多个线程中,需要使用同一个事务管理器,并且在事务范围内执行更新操作。
  2. 保证线程安全:在多线程环境下,多个线程并发地更新同一张表可能会导致数据不一致。因此,在更新操作时,需要使用线程同步机制,例如使用synchronized关键字或者Lock接口。
  3. 优化性能:使用线程池可以有效地减少线程的创建和销毁,提高程序的性能。

下面是一个使用mybatis-plus更新五张不同表的示例代码:

@Service
public class UpdateService {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@Autowiredprivate Table1Mapper table1Mapper;@Autowiredprivate Table2Mapper table2Mapper;@Autowiredprivate Table3Mapper table3Mapper;@Autowiredprivate Table4Mapper table4Mapper;@Autowiredprivate Table5Mapper table5Mapper;public void updateAllTables() {// 开启事务transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {// 使用线程池异步更新五张表taskExecutor.execute(() -> updateTable1());taskExecutor.execute(() -> updateTable2());taskExecutor.execute(() -> updateTable3());taskExecutor.execute(() -> updateTable4());taskExecutor.execute(() -> updateTable5());}});}private synchronized void updateTable1() {// 更新表1table1Mapper.updateById(new Table1());}private synchronized void updateTable2() {// 更新表2table2Mapper.updateById(new Table2());}private synchronized void updateTable3() {// 更新表3table3Mapper.updateById(new Table3());}private synchronized void updateTable4() {// 更新表4table4Mapper.updateById(new Table4());}private synchronized void updateTable5() {// 更新表5table5Mapper.updateById(new Table5());}
}

在上述代码中,我们使用了TransactionTemplate和ThreadPoolTaskExecutor来保证事务和线程安全。在updateAllTables方法中,我们使用TransactionTemplate开启事务,并使用线程池异步更新五张表。在每个更新方法中,使用synchronized关键字来保证线程安全。

需要注意的是,在使用线程池时,线程池的大小需要根据系统的实际情况进行调整,以避免线程池过大或过小导致的性能问题。 ```

方案四:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Service
public class UserService {
@Autowired
private UserMapper userMapper;public void updateUser(int userId, String userName) {UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.eq("user_id", userId);updateWrapper.set("user_name", userName);userMapper.update(null, updateWrapper);
}public void testAsyncUpdate() throws InterruptedException {// 创建一个 CountDownLatch 对象,并设置计数器为 5CountDownLatch countDownLatch = new CountDownLatch(5);// 创建一个线程池ExecutorService executorService = Executors.newFixedThreadPool(5);// 启动 5 个线程,每个线程负责更新一张表for (int i = 0; i < 5; i++) {executorService.submit(() -> {// 获取当前线程的 idint threadId = Thread.currentThread().getId();// 获取要更新的表名String tableName = "user_" + threadId;// 创建一个 QueryWrapper 对象QueryWrapper<User> queryWrapper = new QueryWrapper<>();// 设置查询条件queryWrapper.eq("user_id", threadId);// 查询数据User user = userMapper.selectOne(queryWrapper);// 更新数据updateUser(threadId, user.getUserName() + "_update");// 计数器减一countDownLatch.countDown();});}// 等待所有线程执行完毕countDownLatch.await();// 关闭线程池executorService.shutdown();}
}

在上述示例中,我们使用了 mybatis-plus 的 QueryWrapperUpdateWrapper 对象来构建查询条件和更新条件。我们还使用了 CountDownLatch 对象来等待所有线程执行完毕。

在保证事务和线程安全的情况下,做到异步更新,可以通过以下方式实现:

  1. 使用 synchronized 关键字来保证方法的线程安全。
  2. 使用 @Transactional 注解来开启事务。
  3. 使用 ExecutorService 来创建线程池。
  4. 使用 submit() 方法来启动线程。
  5. 使用 countDownLatch.await() 方法来等待所有线程执行完毕。
  6. 使用 countDownLatch.countDown() 方法来减小计数器

通过以上方式,我们可以保证事务和线程安全的情况下,做到异步更新。

方案五:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.util.concurrent.CompletableFuture;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.concurrent.ExecutionException;public class MybatisPlusAsyncUpdateExample {private static final String NAMESPACE = "com.example.mybatisplus.mapper.UserMapper";@Transactionalpublic static void main(String[] args) throws ExecutionException, InterruptedException {// 创建五个线程,每个线程负责更新一张表List<CompletableFuture<Void>> futures = new ArrayList<>();for (int i = 0; i < 5; i++) {futures.add(updateAsync(i));}// 等待所有线程执行完成CompletableFuture.allOf(futures).join();}private static CompletableFuture<Void> updateAsync(int tableIndex) {return CompletableFuture.runAsync(() -> {// 获取 UserMapper 接口IService<User> userService = SpringContextHolder.getBean(NAMESPACE + ".UserService");// 创建 QueryWrapper 对象QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("id", tableIndex);// 更新数据userService.update(queryWrapper);});}static class User {private Long id;private String name;}
}

在上述示例中,我们使用了 CompletableFuture 来实现异步更新。CompletableFuture 是一个异步计算工具,它可以让我们以异步的方式执行任务,并在任务完成时获取结果。

在示例中,我们创建了五个 CompletableFuture 对象,每个 CompletableFuture 对象对应一个线程,每个线程负责更新一张表。我们使用 CompletableFuture.allOf() 方法等待所有线程执行完成,然后再继续执行后续的代码。

这样,我们就实现了在保证事务和线程安全的情况下,做到异步更新。

方案六:

@Service
@Transactional
public class AsyncUpdateService {@Autowiredprivate Table1Mapper table1Mapper;@Autowiredprivate Table2Mapper table2Mapper;@Autowiredprivate Table3Mapper table3Mapper;@Autowiredprivate Table4Mapper table4Mapper;@Autowiredprivate Table5Mapper table5Mapper;public void asyncUpdate() {CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {table1Mapper.updateTable1();});CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {table2Mapper.updateTable2();});CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> {table3Mapper.updateTable3();});CompletableFuture<Void> future4 = CompletableFuture.runAsync(() -> {table4Mapper.updateTable4();});CompletableFuture<Void> future5 = CompletableFuture.runAsync(() -> {table5Mapper.updateTable5();});CompletableFuture.allOf(future1, future2, future3, future4, future5).join();}
}

在这个示例中,我们使用了CompletableFuture.runAsync()方法来异步更新每张表。每个CompletableFuture都在自己的线程中执行,保证了线程安全性。同时,我们使用了CompletableFuture.allOf()方法来等待所有CompletableFuture完成,保证了事务的一致性。

需要注意的是,这个示例中使用了@Transactional注解来保证事务的一致性。如果在实际项目中使用,需要根据具体情况来选择是否需要事务。同时,需要根据具体情况来调整线程池的大小,以充分利用系统资源

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

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

相关文章

【JUC】二十七、synchronized锁升级之无锁

文章目录 1、背景2、Monitor、Java对象、线程如何关联起来的&#xff1f;3、synchronized锁升级4、锁升级之无锁 关于synchronized同步&#xff0c;能用无锁结构就不要用锁&#xff1b;能锁块&#xff0c;就不要锁整个方法&#xff1b;能用对象锁&#xff0c;就不要用类锁。 用…

【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试【单调栈】2023C-找最小数【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录 题目描述与示例题目描述输入输出示例一输入输出说明 示例二输入输出 示例三输入输出 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 给一个正整数 NUM1&#xff0c;计算出新正整数 NUM2。NUM2 为 NUM1 中移…

LDO和DCDC的区别

目录标题 前言什么是LDO&#xff1f;什么是DCDC&#xff1f;LDO和DCDC的主要区别 前言 对于初学者来说&#xff0c;最常见到的LDO就是最小系统板上自带的低压差线性稳压器&#xff0c;其用于将USB输入的5V电压转化为3.3V供给单片机。最长用到DCDC器件&#xff0c;就是在做小车…

python算法例18 滑动窗口的最大值

1. 问题描述 给定一个可能包含重复整数的数组和一个大小为k的滑动窗口&#xff0c;从左到右在数组中滑动这个窗口&#xff0c;找到数组中每个窗口内的最大值。 2. 问题示例 给出数组[1&#xff0c;2&#xff0c;7&#xff0c;7&#xff0c;8]&#xff0c;滑动窗口大小为k3&a…

Redis - 主从集群下的主从复制原理

主从复制过程 数据同步演变过程 sync 同步 Redis 2.8 版本之前&#xff0c;首次通信成功后&#xff0c; slave 会向 master 发送 sync 数据同步请求。然后 master 就会将其所有数据全部发送给 slave &#xff0c;由 slave 保存到其本地的持久化文件中。这个过 程…

推荐10款值得信赖的办公软件app,为你的工作提效!

在如今的工作环境中&#xff0c;人们需要经常使用各种办公软件来提高工作效率&#xff0c;同时也帮助我们更好地管理自己的工作和生活。以下是推荐10款值得信赖的办公软件app&#xff1a; 1、Evernote – Evernote是一款非常流行的笔记应用程序&#xff0c;适用于多个平台。它…

conda的安装及使用 以pycharm 为例

下载 https://docs.conda.io/en/latest/miniconda.html 下载 window版本 74M且下着吧。 安装 一路next或agree &#xff0c;不同意人家也不会按装 。重要的是安装目录 让andconda当老大 pycharm的使用 创建项目时如下图选择 成功后进入项目的Terminal则如下图表示成功

快速二维相位解包算法基于按照非连续路径进行可靠性排序

Miguel Arevallilo Herra ez, David R. Burton, Michael J. Lalor, and Munther A. Gdeisat 摘要&#xff1a; 据我们所知&#xff0c;我们描述了一种新的相位展开技术。已经提出了几种基于首先展开最可靠像素的算法。这些仅限于连续路径&#xff0c;并且在定义起始像素时会遇…

目前进度记录

目前已经把之前记录的方法都实现了&#xff0c;目前的主函数可以写的更简单比如 int main(int argc, char* argv[]) {KernelClass::create_kernel();MPI_Init(&argc, &argv);kernel().mpi_manager.init_mpi(argc, argv);//创建种群int group1 kernel().conn_manger.c…

山西教资面试---结构化真题125道

文章目录 第一章 教育教学类单元1&#xff1a;应急应变&#xff08;1-21&#xff09;单元2&#xff1a;日常管理&#xff08;22-54&#xff09;单元3&#xff1a;人际关系&#xff08;55-66&#xff09; 第二章 综合分析类单元4&#xff1a;社会现象&#xff08;66-112&#xf…

Python特征工程神器:Feature Engine库详解与实战

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 特征工程是机器学习中至关重要的一环&#xff0c;而Feature Engine库作为Python中的强大特征工程工具&#xff0c;提供了丰富的功能和灵活的操作。本文将深入探讨Feature Engine的各种特性&#xff0c;包括缺失值…

torch.bmm

在PyTorch中&#xff0c;torch.bmm函数用于执行批量矩阵相乘&#xff08;Batch Matrix Multiplication&#xff09;。它接受三维张量作为输入&#xff0c;并执行批量矩阵相乘的操作。 具体来说&#xff0c;假设我们有两个输入张量A和B&#xff0c;它们的维度分别为 &#xff…

单片机的低功耗模式介绍

文章目录 简介一、功耗来源说明1.1、芯片工作模式1.2、静态损耗1.3、I/O额外损耗1.4、动态损耗 二、功耗如何测量三、降低功耗有什么方法3.1、选取合适的芯片工作模式3.2、降低工作频率3.3、关闭不需要使用的外设3.4、 降低静态电流损耗3.5、 周期采集供电3.6、 设置IO口状态 四…

HNU数据库大作业-世界杯比赛系统

前言 之前做的那个版本bug较多&#xff0c;后进行了大量优化。 此项目是一个前后端分离的项目&#xff0c;前端主要使用htmlcssjs搭建&#xff0c;使用的是layui框架 后端使用php语言&#xff0c;仅实现了简单的查询数据库功能&#xff0c;无法实现多并发查询等复杂情况 数…

云架构俭约之道七法则(The Frugal Architect)

文章目录 一、前言关于 Law 与 Rule 的区别 二、云架构俭约之道七法则Design&#xff08;设计方面&#xff09;Law 1&#xff1a;把成本作为非功能性需求Law 2&#xff1a;可持续性系统需要将成本与业务相匹配Law 3&#xff1a;架构设计是一系列权衡的取舍 Measure&#xff08;…

iOS加密CoreML模型

生成模型加密密钥 必须在Xcode的Preferences的Accounts页面登录Apple ID&#xff0c;才能在Xcode中生成模型加密密钥。 在Xcode中打开模型&#xff0c;单击Utilities选项卡&#xff0c;然后单击“Create Encryption Key”按钮。 从下拉菜单中选择当前App的Personal Team&…

多项目同时进行如何做好进度管理?

许多企业都面临着同时进行多个项目的情况&#xff0c;因此项目经理经常需要管理多个项目。多项目管理的难点不仅在于项目数量增加&#xff0c;还在于资源分配不均、难以监控多个项目进度以及复杂的沟通协作。 一、从项目经理的角度分析 首先&#xff0c;要把握高效项目管理的几…

蚂蚁SEO实用的网络baidu蜘蛛有哪些

网络蜘蛛是一种用于从互联网上自动抓取信息的程序。它们根据给定的规则和指令&#xff0c;遍历网站上的页面&#xff0c;收集信息并将其存储在数据库中。网络蜘蛛在搜索引擎、数据挖掘、信息提取等领域有着广泛的应用。本文将介绍一种实用的网络蜘蛛&#xff0c;并探讨其实现原…

视频号小店与小商店有什么区别?一篇文章带你了解!

我是电商珠珠 视频号小店和小商店都是腾讯开发出来的电商平台&#xff0c;视频号小店出现的比小商店要晚一些&#xff0c;所以很多想入驻的新手&#xff0c;在这两者之间容易混淆。 下面我就来跟大家详细的讲一下&#xff0c;这两者之间区别。 1、团队不同 虽然都是腾讯公司…

MySQL——库,表基础操作

目录 一.库的操作 1.显示当前的数据库列表 2.创建数据库 3.字符集和校验规则 4.操纵数据库 5.删除数据库 6.数据库备份与还原 7.查看连接情况 二.表的操作 1.创建表 2.查看表结构 3.修改表 4.删除表 一.库的操作 1.显示当前的数据库列表 show databases; 2.创建数…