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 {
    
    @Autowired
    private AsyncService asyncService;
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    public void updateMultipleTables(UpdateRequest request) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                asyncService.updateTableA(request.getTableAData());
                asyncService.updateTableB(request.getTableBData());
                asyncService.updateTableC(request.getTableCData());
            }
        });
    }
}

@Service
public class AsyncService {
    
    @Autowired
    private TableAService tableAService;
    
    @Autowired
    private TableBService tableBService;
    
    @Autowired
    private TableCService tableCService;
    
    @Async
    public void updateTableA(TableAData data) {
        tableAService.update(data);
    }
    
    @Async
    public void updateTableB(TableBData data) {
        tableBService.update(data);
    }
    
    @Async
    public 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 {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private Table1Mapper table1Mapper;

    @Autowired
    private Table2Mapper table2Mapper;

    @Autowired
    private Table3Mapper table3Mapper;

    @Autowired
    private Table4Mapper table4Mapper;

    @Autowired
    private Table5Mapper table5Mapper;

    public void updateAllTables() {
        // 开启事务
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                // 使用线程池异步更新五张表
                taskExecutor.execute(() -> updateTable1());
                taskExecutor.execute(() -> updateTable2());
                taskExecutor.execute(() -> updateTable3());
                taskExecutor.execute(() -> updateTable4());
                taskExecutor.execute(() -> updateTable5());
            }
        });
    }

    private synchronized void updateTable1() {
        // 更新表1
        table1Mapper.updateById(new Table1());
    }

    private synchronized void updateTable2() {
        // 更新表2
        table2Mapper.updateById(new Table2());
    }

    private synchronized void updateTable3() {
        // 更新表3
        table3Mapper.updateById(new Table3());
    }

    private synchronized void updateTable4() {
        // 更新表4
        table4Mapper.updateById(new Table4());
    }

    private synchronized void updateTable5() {
        // 更新表5
        table5Mapper.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 对象,并设置计数器为 5
    CountDownLatch countDownLatch = new CountDownLatch(5);

    // 创建一个线程池
    ExecutorService executorService = Executors.newFixedThreadPool(5);

    // 启动 5 个线程,每个线程负责更新一张表
    for (int i = 0; i < 5; i++) {
        executorService.submit(() -> {
            // 获取当前线程的 id
            int 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";

    @Transactional
    public 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 {

    @Autowired
    private Table1Mapper table1Mapper;

    @Autowired
    private Table2Mapper table2Mapper;

    @Autowired
    private Table3Mapper table3Mapper;

    @Autowired
    private Table4Mapper table4Mapper;

    @Autowired
    private 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注解来保证事务的一致性。如果在实际项目中使用,需要根据具体情况来选择是否需要事务。同时,需要根据具体情况来调整线程池的大小,以充分利用系统资源文章来源地址https://www.toymoban.com/news/detail-847151.html

到了这里,关于Mybatis-plus更新多张表,保证事务安全的情况下使用异步多线程实现(待验证)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • mybatis-plus更新字段为null值

    mybatis-plus相信大家都不陌生所以不在介绍 首先我们先看一下mybatis-plus的官网上的介绍  官网推荐的有三种方式可以实现 第一种:调整全局策略, mybatis-plus默认的全局策略为NOT_NULL非空默认策略,其实就是当更新是某个字段为空,则不对该字段进行更新,这也是我们常用的策略所此种

    2024年02月14日
    浏览(55)
  • 批量插入或更新数据(MyBatis-plus框架)

    目录 1.场景说明 2.DUPLICATE 和REPLACE比较 3.批量插入或者更新(两种方式) 方式一:mybatis-plus的saveOrUpdateBatch方法 问题:如果操作类集成了基础类,比如封装了BaseEntity去集成,那么这样使用会出问题 方式二:on duplicate key (推荐) 4.注意 5.常见问题  插入数据时,我们经常会遇到这

    2024年02月04日
    浏览(88)
  • MyBatis-Plus中的更新操作(通过id更新和条件更新)

    目录 前言 一、通过id更新 二、条件更新 2.1 使用QueryWrapper进行条件更新 2.2 使用UpdateWrapper进行条件更新 总结  本文学习MP中的更新操作方法,带大家一起查看源码,了解更新操作的方法。学会熟练地去运用更新方法解决自己在项目中的问题。 Mybatis-Plus知识点[MyBatis+MyBatis-Pl

    2024年02月06日
    浏览(52)
  • Mybatis-plus通过其他字段批量更新或新增

    根据某个或者多个非ID字段进行批量更新 示例通过名称与id两个字段更新 引用mybatis-plus根据某个指定字段批量更新数据库 通过其他字段批量更新或新增

    2024年02月12日
    浏览(50)
  • mybatis-plus update更新操作(三种方式)

    MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 愿景 我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。 方式一(UpdateWrapper 条件构造器) 方

    2024年02月11日
    浏览(61)
  • MyBatis-plus更新对象时将字段值更新为null

            mybatis-plus在执行更新操作,当更新字段为 空字符串 或者 null 的则不会执行更新。如果要将指定字段更新null,可以通过以下三种方式实现。 1、全局配置         可以在 application.yml 配置文件中注入配置 GlobalConfiguration 属性 update-strategy, 将 update-strategy 策略调

    2024年02月15日
    浏览(60)
  • Mybatis-Plus不能更新对象字段为空值问题解决

    问题描述: 在使用Mybatis-Plus调用updateById方法进行数据更新默认情况下是不能更新空值字段的,而在实际开发过程中,往往会遇到需要将字段值更新为空值的情况,该如何解决呢? 原因分析: Mybatis-Plus中字段的更新策略是通过FieldStrategy属性控制的。在实体字段上,如果不通

    2024年02月12日
    浏览(52)
  • Springboot+mybatis-plus+dynamic-datasource+Druid 多数据源 分布式事务

    背景 处理多数据源事务一直是一个复杂而棘手的问题,通常我们有两种主流的解决方法。 第一种是通过Atomikos手动创建多数据源事务,这种方法更适合数据源数量较少,参数配置不复杂,对性能要求不高的项目。然而,这种方法的最大困难在于需要手动配置大量设置,这可能

    2024年02月11日
    浏览(40)
  • 【Mybatis-Plus】mybatisplus更新时,实体字段为空,数据库不更新的解决方案

    项目技术栈:jdk (1.8) + spring boot (2.1.0) + mybatis-plus (3.5.1) 数据库: MySQL 字段类型:varchar 和 Integer 从前端传过来的数据实体字段, convertType 和 step 设为null时,使用mybatis-plus 的 updateById方法往数据库中更新时,这两个字段不更新,数据不为空可以插入。 mybatis-plus在更新的时候做

    2024年01月16日
    浏览(63)
  • MyBatis-Plus 更新(update)方法,属性参数为空时进行更新与不进行更新的设置

    解决方案: 在实体类上使用@TableField注解 FieldStrategy的源码中,一共有4种策略类型。 附上mybatis-plus官网链接地址: https://baomidou.com/pages/223848/#fieldstrategy 有兴趣的小伙伴可以点击看看

    2024年02月11日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包