Magic-api(1.7.5)集成seata实现跨库分布式事务

        magic-api 是一个基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象即可完成常见的HTTP API接口开发。解决了应用部署 编译-打包-部署等一系列上线操作流程;实现接口的快速开发上线等等。同时它还支持多数据源下的数据操作,解决了各个数据库之间的数据交互问题。但是当前版本下并未实现跨数据源分布式事务,在多数据源数据写入时有可能会造成“脏数据”。当前市面上有很多实现分布式事务的产品,最终选择seata来扩展magic的事务功能。

        由于我是一个springcloud项目,从seata官方案例中我们知道想要集成seata需要将DataSource外面再包一层DataSourceProxy

seata-案例传送门)

首先我们拉去magic-api的源码

magic-api传送门

现在我们要找到magic-api(我用的是1.7.5)的DataSource注册方法org.ssssssss.magicapi.provider.impl.DefaultMagicAPIService下的createDataSource方法


    private DataSource createDataSource(DataSourceInfo properties) {
        Class<? extends DataSource> dataSourceType = getDataSourceType(properties.get("type"));
        if (!properties.containsKey("driverClassName")
                && properties.containsKey("url")) {
            String url = properties.get("url");
            String driverClass = DatabaseDriver.fromJdbcUrl(url).getDriverClassName();
            properties.put("driverClassName", driverClass);
        }
        DataSource dataSource = BeanUtils.instantiateClass(dataSourceType);
        ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
        ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();
        aliases.addAliases("url", "jdbc-url");
        aliases.addAliases("username", "user");
        Binder binder = new Binder(source.withAliases(aliases));
        binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(dataSource));
        //这里在DataSource 包一层DataSourceProxy 然后返回代理后的DataSource 
        DataSourceProxy dataSourceProxy = new DataSourceProxy(dataSource);
        return dataSourceProxy;
}

注意:如果缺包的话记得maven引入seata的包

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-seata</artifactId>
            <version>2.1.0.RELEASE</version>
            <exclusions>
                <exclusion>
                    <artifactId>seata-all</artifactId>
                    <groupId>io.seata</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>1.3.0</version>
        </dependency>

        然后在org.ssssssss.magicapi.modules.SQLModule中新增一个方法来获取全局事务对象GlobalTransaction

    @Comment("开启分布式事务,返回事务对象")
    public GlobalTransaction globalTransaction() {
        GlobalTransaction tx = GlobalTransactionContext.getCurrentOrCreate();
        return tx;
    }

然后将整个magic-api项目编译打包并将magic-api-1.7.5.jar加载到maven本地库,加载脚本如下。

mvn install:install-file -Dfile=D:\programs\java\magic-api\magic-api\target\magic-api-1.7.5.jar -DgroupId=org.ssssssss -DartifactId=magic-api -Dversion=1.7.5 -Dpackaging=jar

 在项目中引入seata的配置重载项目将新magic-api与seata加载到项目中。这样就集成完成了,我们按照seata官方的指引在项目中引入file.conf和registry.conf启动seata-server,启动项目就可以安心进行跨库操作了。

测试一下(下面是在magic-api中写api脚本):

//获取全局事务
var tx = db.globalTransaction();
try {
  //启动全局事务
    tx.begin(10000, "test-client");
    var sql = """insert into t_test(test) values ('aa')"""
    //不同数据源写入操作
    db.ry_cloud.update(sql)
    db.inside_db.update(sql)
    throw '来个错误' //测试下报错
} catch (e) {
//报错回滚
    tx.rollback();
    log.info("报错啦!错误信息:{}", e.getMessage())
    exit 400, e.getMessage()
}
//正常提交
tx.commit();

运行结果:

03/02 14:40 INFO o.s.m.c.MappingHandlerMapping : 刷新接口:测试,POST:/system_api/third_api/test
03/02 14:40 INFO r.b.i.CustomRequestInterceptor: 用户:[null],请求接口:[测试],请求参数:null,请求体:null
03/02 14:40 INFO s.t.a.DefaultGlobalTransaction: Begin new global transaction [10.51.64.62:8091:2004416281]
要执行的SQL:insert into t_test(test) values ('aa')
要执行的SQL参数:[]
03/02 14:40 INFO 测试(/system_api/third_api/test): 执行SQL:insert into t_test(test) values ('aa')
03/02 14:40 INFO 测试(/system_api/third_api/test): 数据源:主数据源
要执行的SQL:insert into t_test(test) values ('aa')
要执行的SQL参数:[]
03/02 14:40 INFO 测试(/system_api/third_api/test): 执行SQL:insert into t_test(test) values ('aa')
03/02 14:40 INFO 测试(/system_api/third_api/test): 数据源:内网数据库
03/02 14:40 INFO .p.c.RmBranchRollbackProcessor: rm handle branch rollback process:xid=10.51.64.62:8091:2004416281,branchId=2004416285,branchType=AT,resourceId=jdbc:mysql://mysql.com:3306/data_trans,applicationData=null
03/02 14:40 INFO io.seata.rm.AbstractRMHandler : Branch Rollbacking: 10.51.64.62:8091:2004416281 2004416285 jdbc:mysql://mysql.com:3306/data_trans
03/02 14:40 INFO s.r.d.u.AbstractUndoLogManager: xid 10.51.64.62:8091:2004416281 branch 2004416285, undo_log deleted with GlobalFinished
03/02 14:40 INFO io.seata.rm.AbstractRMHandler : Branch Rollbacked result: PhaseTwo_Rollbacked
03/02 14:40 INFO .p.c.RmBranchRollbackProcessor: rm handle branch rollback process:xid=10.51.64.62:8091:2004416281,branchId=2004416283,branchType=AT,resourceId=jdbc:mysql://mysql.com:3306/ry_cloud,applicationData=null
03/02 14:40 INFO io.seata.rm.AbstractRMHandler : Branch Rollbacking: 10.51.64.62:8091:2004416281 2004416283 jdbc:mysql://mysql.com:3306/ry_cloud
03/02 14:40 INFO s.r.d.u.AbstractUndoLogManager: xid 10.51.64.62:8091:2004416281 branch 2004416283, undo_log deleted with GlobalFinished
03/02 14:40 INFO io.seata.rm.AbstractRMHandler : Branch Rollbacked result: PhaseTwo_Rollbacked
03/02 14:40 INFO s.t.a.DefaultGlobalTransaction: [10.51.64.62:8091:2004416281] rollback status: Rollbacked
03/02 14:40 INFO 测试(/system_api/third_api/test): 报错啦!错误信息:来个错误

查看两个数据库中的t_test表 数据未写入。去掉事务代码虽然报错了但是两个库中的表数据都插入成功。分布式事务集成成功。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值