seata整合mybatis-plus时分页和乐观锁插件失效解决

seata整合mybatis-plus时需要使用seata的数据源代理,

import io.seata.rm.datasource.DataSourceProxy;代码如下。

版本为 seata 0.9  myabtis-plus3.5.2

package com.huanglong.shopping.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;

import com.huanglong.shopping.enums.OrderStatusEnum;
import io.seata.rm.datasource.DataSourceProxy;

import org.apache.ibatis.type.EnumOrdinalTypeHandler;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**

 * 使用Seata对数据源进行代理
 */
@Configuration
public class DataSourceProxyConfig {
    @Value("${mybatis-plus.mapper-locations}")
    private String mapperLocations;

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }

    @Bean
    public DataSourceProxy dataSourceProxy(DataSource dataSource) {
        return new DataSourceProxy(dataSource);
    }

    @Bean
    public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSourceProxy);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());

//     分页 重新配置
        MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor=new PaginationInnerInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
          sqlSessionFactoryBean.setPlugins(mybatisPlusInterceptor);

        /*         解决seata整合mybatis-plus时乐观锁失效问题   */
        OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor=new OptimisticLockerInnerInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);
        sqlSessionFactoryBean.setPlugins(mybatisPlusInterceptor);


        return sqlSessionFactoryBean;
    }

}
package com.huanglong.shopping.config;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

/**
 * @auther zzyy
 * @create 2019-12-11 16:57
 */
@Configuration
@MapperScan({"com.huanglong.shopping.mapper"})
public class MyBatisConfig {
}

Seata整合Mybatis-Plus来处理多数据源事务问题,主要是通过以下几个步骤实现的: 1. 安装Mybatis-PlusSeata插件: 确保你的Mybatis-Plus版本支持Seata插件。可以在`mybatis-plus-generator`的`pom.xml`或`build.gradle`文件中添加SeataMybatis-Plus插件依赖。 对于Maven: ```xml <dependency> <groupId>com.baomidou.mybatisplus.extension</groupId> <artifactId>mybatis-plus-extension-boot-starter</artifactId> <!-- Add this if using with Seata --> <exclusions> <exclusion> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata-mybatisplus</artifactId> </dependency> ``` 对于Gradle: ```gradle implementation 'com.baomidou.mybatisplus.extension:mybatis-plus-extension-boot-starter' implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-seata-mybatisplus' ``` 2. 配置数据源Seata: 在Spring Boot的配置文件中(通常是`application.properties`或`application.yml`),继续配置多个数据源以及Seata的相关参数,如RMS地址等。 3. 注册数据源工厂: 创建一个数据源工厂类,用于根据不同业务场景选择对应的数据源: ```java @Configuration public class MultiDataSourceConfig { @Value("${spring.datasource.type}") private String dataSourceType; @Bean @Primary @ConfigurationProperties(prefix = "spring.datasource.${dataSourceType}.") public DataSource masterDataSource() { // ... 实例化主数据源 } @Bean @ConfigurationProperties(prefix = "spring.datasource.secondary.") public DataSource secondaryDataSource() { // ... 实例化从数据源 } @Bean public DataSourceSelector dataSourceSelector() { return () -> { DataSourceContextHolder.setDataSource(dataSourceType); return dataSourceType.equals("primary") ? primaryDataSource() : secondaryDataSource(); }; } } ``` 4. 配置事务管理器: 在`application.yml`或`application.properties`中指定Seata的全局事务管理器(Global Transaction Manager),并启用Mybatis-Plus的分库分表注解支持: ```yaml spring: cloud: alibaba: seata: global-tran-manager-type: JDBC registry-center-config: type: NAMESPACE address: localhost:9091 mybatis-plus: db-config: default-split-sharding-condition-provider-type: TABLE ``` 5. 开始事务: 在Service或Repository层中,使用`@GlobalTransactional`注解启动Seata全局事务,然后在需要操作多数据源的地方插入相应的数据源切换: ```java @Service public class MyService { @Autowired private SeataTemplate seataTemplate; @GlobalTransactional(name = "transactionGroup", rollbackFor = Exception.class) public void multiDataSourceOperation() { // 切换到主数据源 DataSourceContextHolder.setDataSource("primary"); PrimaryDatabaseOperations primaryOps = new PrimaryDatabaseOperations(seataTemplate); // 执行主数据源操作 // 切换到从数据源 DataSourceContextHolder.setDataSource("secondary"); SecondaryDatabaseOperations secondaryOps = new SecondaryDatabaseOperations(seataTemplate); // 执行从数据源操作 } } ``` 当交易完成时,Seata会自动提交或回滚事务,确保跨数据源的事务一致性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值