Spring Cloud Alibaba 初體驗(六) Seata 及結合 MyBatis 與 MyBatis-Plus 的使用


一、下載與運行

本文使用 Seata 1.1.0:https://github.com/seata/seata/releases

Windows 環境下雙擊 bin/seata-server.bat 啟動 Seata Server

二、結合 MyBatis 使用

以 Service1 為例

2.1 添加引用

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

2.2 添加配置

2.2.1 registry.conf

Spring Cloud 快速集成 Seata 復制

放置在 resources 目錄,內容詳見代碼,均采用了默認配置

2.2.2 file.conf

Spring Cloud 快速集成 Seata 復制

放置在 resources 目錄,內容詳見代碼,均采用了默認配置

2.2.3 yml 配置

spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group

注意

file.conf 中 vgroup_mapping 的 key 值為 my_test_tx_group:

service {
  vgroup_mapping.my_test_tx_group = "default"
}

則 yml 中 tx-service-group 的值也必須為 my_test_tx_group;如果 vgroup_mapping 的 key 值改為 abcdefg,則 yml 中 tx-service-group 的值也必須為 abcdefg,即這兩個值必須保持一致,否則會報錯:

no available service 'null' found, please make sure registry config correct

2.2.4 添加數據源配置

@Configuration
public class DataSourceProxyConfig {

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

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:/mapper/*.xml"));
        return factoryBean.getObject();
    }
}

在2.2.0.RELEASE及以后,數據源代理自動實現了,不需要再手動去配置一個代理類,官方文檔還需要配置 DataSourceProxy 應該是文檔沒有及時更新

2.2.5 添加 undo_log 表

在業務相關的數據庫中添加 undo_log 表,用於保存需要回滾的數據

CREATE TABLE `undo_log`
(
    `id`            BIGINT(20)   NOT NULL AUTO_INCREMENT,
    `branch_id`     BIGINT(20)   NOT NULL,
    `xid`           VARCHAR(100) NOT NULL,
    `context`       VARCHAR(128) NOT NULL,
    `rollback_info` LONGBLOB     NOT NULL,
    `log_status`    INT(11)      NOT NULL,
    `log_created`   DATETIME     NOT NULL,
    `log_modified`  DATETIME     NOT NULL,
    `ext`           VARCHAR(100) DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8

2.3 使用

添加 @GlobalTransactional 注解即可

@Service
public class BusinessServiceImpl implements BusinessService {

    @Reference
    private StorageService storageService;
    @Reference
    private OrderService orderService;

    @GlobalTransactional
    @Override
    public void purchase(Order order) throws Exception {
        storageService.deduct(order.getCommodityCode(), order.getCount());
        orderService.create(order);
    }
}

三、結合 MyBatis-Plus 使用

與在 MyBatis 中使用類似,區別在於數據源的配置

3.1 錯誤配置

@Configuration
public class DataSourceProxyConfig {

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

//    @Bean
//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
//        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//        factoryBean.setDataSource(dataSource);
//        factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
//                .getResources("classpath*:/mapper/*.xml"));
//        return factoryBean.getObject();
//    }

    @Bean
    @ConfigurationProperties(prefix = "mybatis-plus")
    public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws IOException {
        // 這里用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否則 MyBatisPlus 不會生效
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:/mapper/mapper/*.xml"));
        return mybatisSqlSessionFactoryBean;
    }
}

上面配置是參考 seata-samples 中的配置,雖然可以正常使用,但是造成 MyBatis-Plus 的插件如分頁等不生效

3.2 正確配置

public class DataSourceProxyConfig {

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

僅配置 DataSource 即可

完整代碼:GitHub

Seata 1.1.0 及之后版本支持直接在 application.yml 添加配置,可以替換掉 registry.conf 和 file.conf,本人暫未測試

參考

  1. Spring Cloud 快速集成 Seata
  2. Seata初試采坑
  3. 二、springboot項目使用seata實現分布式事務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM