本文最后更新于:2025年5月30日 下午
ShardingSphere5.2.1 + Seata1.6.1
准备
外围环境
1、Nacos服务
nacos官网地址:https://nacos.io/zh-cn/
Nacos服务下载地址:https://github.com/alibaba/nacos/releases?page=2
详情请移步nacos笔记查看。
2、Seata服务 1.6.1
Seata官网地址:https://seata.apache.org/zh-cn/release-history/seata-server
springboot2.7.18对应的springcloud alibaba下的seata就是1.6.1版本
详情请移步seata笔记查看。
3、mysql 5.7(搭配MGR实现高可用集群)
高可用是搭配动态数据源策略使用的,这里也可以不用高可用,那样的话就采取静态策略即可。
详情请移步mysqlMGR集群笔记查看。
步骤
Maven依赖
父类依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.7.18</version > </parent > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <spring-cloud-alibaba.version > 2021.0.5.0</spring-cloud-alibaba.version > <spring-cloud.version > 2021.0.5</spring-cloud.version > <snakeyaml.version > 1.33</snakeyaml.version > <druid.version > 1.2.6</druid.version > <knife4j-openapi2-spring-boot-starter.version > 4.4.0</knife4j-openapi2-spring-boot-starter.version > <hutool.version > 5.8.34</hutool.version > </properties > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-dependencies</artifactId > <version > ${spring-cloud.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > com.alibaba.cloud</groupId > <artifactId > spring-cloud-alibaba-dependencies</artifactId > <version > ${spring-cloud-alibaba.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.yaml</groupId > <artifactId > snakeyaml</artifactId > <version > ${snakeyaml.version}</version > </dependency > <dependency > <groupId > org.liquibase</groupId > <artifactId > liquibase-core</artifactId > <version > ${liquibase-core.version}</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > ${druid.version}</version > </dependency > <dependency > <groupId > com.github.xiaoymin</groupId > <artifactId > knife4j-openapi2-spring-boot-starter</artifactId > <version > ${knife4j-openapi2-spring-boot-starter.version}</version > </dependency > <dependency > <groupId > cn.hutool</groupId > <artifactId > hutool-all</artifactId > <version > ${hutool.version}</version > </dependency > </dependencies > </dependencyManagement >
子类依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 <dependencies > <dependency > <groupId > com.alibaba.cloud</groupId > <artifactId > spring-cloud-starter-alibaba-nacos-discovery</artifactId > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-loadbalancer</artifactId > </dependency > <dependency > <groupId > com.alibaba.cloud</groupId > <artifactId > spring-cloud-starter-alibaba-nacos-config</artifactId > </dependency > <dependency > <groupId > com.alibaba.cloud</groupId > <artifactId > spring-cloud-starter-alibaba-seata</artifactId > <exclusions > <exclusion > <groupId > org.antlr</groupId > <artifactId > antlr4-runtime</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-bootstrap</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.yaml</groupId > <artifactId > snakeyaml</artifactId > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.33</version > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > </dependency > <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.5.3.1</version > </dependency > <dependency > <groupId > org.apache.shardingsphere</groupId > <artifactId > shardingsphere-jdbc-core-spring-boot-starter</artifactId > <version > 5.2.1</version > </dependency > <dependency > <groupId > org.apache.shardingsphere</groupId > <artifactId > shardingsphere-transaction-core</artifactId > <version > 5.2.1</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-aop</artifactId > </dependency > <dependency > <groupId > cn.hutool</groupId > <artifactId > hutool-all</artifactId > </dependency > <dependency > <groupId > com.github.xiaoymin</groupId > <artifactId > knife4j-openapi2-spring-boot-starter</artifactId > </dependency > </dependencies >
application.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 server: port: 10010 spring: application: name: user-service shardingsphere: props: sql-show: true datasource: names: ds_0,ds_1,ds_2 ds_0: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/db_01?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ds_1: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/db_01?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ds_2: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://127.0.0.1:3306/db_01?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver rules: readwrite-splitting: data-sources: rw_1: dynamic-strategy: auto-aware-data-source-name: auto_datasource_1 write-data-source-query-enabled: true load-balancer-name: round-robin load-balancers: round-robin: type: ROUND_ROBIN random: type: RANDOM props: weight: type: WEIGHT props: weight-data-sources: ds_1=1,ds_2=1 transaction-random: type: TRANSACTION_RANDOM transaction_round_robin: type: TRANSACTION_ROUND_ROBIN transaction_weight: type: TRANSACTION_WEIGHT props: weight-data-sources: ds_1=1,ds_2=1 fixed_replica_random: type: FIXED_REPLICA_RANDOM fixed_replica_round_robin: type: FIXED_REPLICA_ROUND_ROBIN fixed_replica_weight: type: FIXED_REPLICA_WEIGHT props: weight-data-sources: ds_1=1,ds_2=1 fixed_primary: type: FIXED_PRIMARY database-discovery: data-sources: auto_datasource_1: data-source-names: - ds_0 - ds_1 - ds_2 discovery-heartbeat-name: hrb_1 discovery-type-name: mgr_1 discovery-heartbeats: hrb_1: props: keep-alive-corn: '0/5 * * * * ?' discovery-types: mgr_1: type: 'MySQL.MGR' props: group-name: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' sharding: tables: t_user: actual-data-nodes: rw_1.t_user_$->{0..1} table-strategy: standard: sharding-column: id sharding-algorithm-name: t-user-inline key-generate-strategy: column: id key-generator-name: snowflake sharding-algorithms: t-user-inline: type: INLINE props: algorithm-expression: t_user_$->{id % 2 } key-generators: snowflake: type: SNOWFLAKE props: worker-id: 1 cloud: nacos: config: group: SEATA_GROUP namespace: public discovery: server-addr: 127.0 .0 .1 :8848 namespace: public group: SEATA_GROUP seata: enabled: true application-id: seata-server tx-service-group: test-tx-group enable-auto-data-source-proxy: false data-source-proxy-mode: AT service: vgroup-mapping: test-tx-group: default grouplist: default: 127.0 .0 .1 :8091
关键配置
在java目录下创建以下文件夹
1 org.apache .shardingsphere .transaction .base .seata .at
新建三个文件
文件1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 package org.apache.shardingsphere.transaction.base.seata.at;import com.google.common.base.Preconditions;import io.seata.config.FileConfiguration;import io.seata.core.context.RootContext;import io.seata.core.exception.TransactionException;import io.seata.core.rpc.netty.RmNettyRemotingClient;import io.seata.core.rpc.netty.TmNettyRemotingClient;import io.seata.rm.RMClient;import io.seata.rm.datasource.DataSourceProxy;import io.seata.tm.TMClient;import io.seata.tm.api.GlobalTransaction;import io.seata.tm.api.GlobalTransactionContext;import lombok.SneakyThrows;import org.apache.shardingsphere.infra.database.type.DatabaseType;import org.apache.shardingsphere.transaction.core.ResourceDataSource;import org.apache.shardingsphere.transaction.core.TransactionType;import org.apache.shardingsphere.transaction.spi.ShardingSphereTransactionManager;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;import java.util.Collection;import java.util.HashMap;import java.util.Map;public final class SeataATShardingSphereTransactionManager implements ShardingSphereTransactionManager { private final Map<String, DataSource> dataSourceMap = new HashMap <>(); private final String applicationId; private final String transactionServiceGroup; private final boolean enableSeataAT; private final int globalTXTimeout; public SeataATShardingSphereTransactionManager () { FileConfiguration config = new FileConfiguration ("seata.conf" ); enableSeataAT = config.getBoolean("sharding.transaction.seata.at.enable" , true ); applicationId = config.getConfig("client.application.id" ); transactionServiceGroup = config.getConfig("client.transaction.service.group" , "default" ); globalTXTimeout = config.getInt("sharding.transaction.seata.tx.timeout" , 60 ); } @Override public void init (final DatabaseType databaseType, final Collection<ResourceDataSource> resourceDataSources, final String providerType) { if (enableSeataAT) { initSeataRPCClient(); resourceDataSources.forEach(each -> dataSourceMap.put(each.getOriginalName(), new DataSourceProxy (each.getDataSource()))); } } private void initSeataRPCClient () { Preconditions.checkNotNull(applicationId, "please config application id within seata.conf file." ); TMClient.init(applicationId, transactionServiceGroup); RMClient.init(applicationId, transactionServiceGroup); } @Override public TransactionType getTransactionType () { return TransactionType.BASE; } @Override public boolean isInTransaction () { Preconditions.checkState(enableSeataAT, "sharding seata-at transaction has been disabled." ); return null != SeataTransactionHolder.get(); } @Override public Connection getConnection (final String databaseName, final String dataSourceName) throws SQLException { Preconditions.checkState(enableSeataAT, "sharding seata-at transaction has been disabled." ); return dataSourceMap.get(databaseName + "." + dataSourceName).getConnection(); } @Override public void begin () { begin(globalTXTimeout); } @Override @SneakyThrows(TransactionException.class) public void begin (final int timeout) { if (timeout < 0 ) { throw new TransactionException ("timeout should more than 0s" ); } Preconditions.checkState(enableSeataAT, "sharding seata-at transaction has been disabled." ); GlobalTransaction globalTransaction = GlobalTransactionContext.getCurrentOrCreate(); globalTransaction.begin(timeout * 1000 ); SeataTransactionHolder.set(globalTransaction); } @Override @SneakyThrows(TransactionException.class) public void commit (final boolean rollbackOnly) { Preconditions.checkState(enableSeataAT, "sharding seata-at transaction has been disabled." ); try { SeataTransactionHolder.get().commit(); } finally { SeataTransactionHolder.clear(); RootContext.unbind(); } } @Override @SneakyThrows(TransactionException.class) public void rollback () { Preconditions.checkState(enableSeataAT, "sharding seata-at transaction has been disabled." ); try { SeataTransactionHolder.get().rollback(); } finally { SeataTransactionHolder.clear(); RootContext.unbind(); } } @Override public void close () { dataSourceMap.clear(); SeataTransactionHolder.clear(); RmNettyRemotingClient.getInstance().destroy(); TmNettyRemotingClient.getInstance().destroy(); } }
文件2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package org.apache.shardingsphere.transaction.base.seata.at;import io.seata.tm.api.GlobalTransaction;import lombok.AccessLevel;import lombok.NoArgsConstructor;@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class SeataTransactionHolder { private static final ThreadLocal<GlobalTransaction> CONTEXT = new ThreadLocal <>(); public static void set (final GlobalTransaction transaction) { CONTEXT.set(transaction); } public static GlobalTransaction get () { return CONTEXT.get(); } public static void clear () { CONTEXT.remove(); } }
文件3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package org.apache.shardingsphere.transaction.base.seata.at;import io.seata.core.context.RootContext;import org.apache.shardingsphere.infra.database.metadata.DataSourceMetaData;import org.apache.shardingsphere.infra.executor.kernel.model.ExecutorDataMap;import org.apache.shardingsphere.infra.executor.sql.hook.SQLExecutionHook;import java.util.List;import java.util.Map;public final class TransactionalSQLExecutionHook implements SQLExecutionHook { private static final String SEATA_TX_XID = "SEATA_TX_XID" ; private boolean seataBranch; @Override public void start (final String dataSourceName, final String sql, final List<Object> parameters, final DataSourceMetaData dataSourceMetaData, final boolean isTrunkThread, final Map<String, Object> shardingExecuteDataMap) { if (isTrunkThread) { if (RootContext.inGlobalTransaction()) { ExecutorDataMap.getValue().put(SEATA_TX_XID, RootContext.getXID()); } } else if (!RootContext.inGlobalTransaction() && shardingExecuteDataMap.containsKey(SEATA_TX_XID)) { RootContext.bind((String) shardingExecuteDataMap.get(SEATA_TX_XID)); seataBranch = true ; } } @Override public void finishSuccess () { if (seataBranch) { RootContext.unbind(); } } @Override public void finishFailure (final Exception cause) { if (seataBranch) { RootContext.unbind(); } } }
在resources目录下创建以下文件夹
这种是使用了SPI机制
新建两个文件
文件1
1 2 3 文件名称:org.apache .shardingsphere .infra .executor .sql .hook .SQLExecutionHook 文件内容: org.apache .shardingsphere .transaction .base .seata .at .TransactionalSQLExecutionHook
文件2
1 2 3 文件名称:org.apache .shardingsphere .transaction .spi .ShardingSphereTransactionManager 文件内容: org.apache .shardingsphere .transaction .base .seata .at .SeataATShardingSphereTransactionManager
使用
调用方
1 2 3 4 5 6 7 @GlobalTransactional(rollbackFor = Exception.class) @ShardingSphereTransactionType(TransactionType.BASE) public void buyItem (OrderDTO orderDTO) { itemClient.update(orderDTO.getItemId(), orderDTO.getAmount()); }
被调用方
1 2 3 4 5 6 7 8 9 @Transactional(rollbackFor = Exception.class) @ShardingSphereTransactionType(TransactionType.BASE) public void updateUserMoney (BigDecimal money, Long id) throws SQLException { int i = userMapper.updateMoney(money, id); if (i == 0 ){ throw new SQLException ("更新失败!" ); } }
注意事项:
枚举类异常问题
shardingsphere
与mybatisplus
一起使用时,对于枚举类可能会出现异常:InvalidDataAccessApiUsageException: Error attempting to get column 'status' from result set. Cause: java.sql.SQLFeatureNotSupportedException: getObject with type。
这主要是因为shardingsphere
与当前版本的mybatisplus
不兼容。
根据参考资料2,mybatisplus3.4.1虽然不会出现这个问题,但是这个版本查询出来的数据,对应的枚举类是null值,也是有问题,3.4.3以上没有这问题,但是又与shardingsphere冲突导致出现枚举类异常,而且mybatisplus官方说不做这个组件的兼容。所以需要自行处理。
方法一:不使用枚举类
既然是枚举类异常,那就不使用枚举类不就好了,这样倒是简单粗暴,但是并不是解决问题的好方法
方法二:自定义类型处理器方法
1、枚举类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.order.enums;import com.baomidou.mybatisplus.annotation.EnumValue;import com.fasterxml.jackson.annotation.JsonValue;import lombok.Getter;@Getter public enum OrderStatusEnums { WAITING_PAYMENT(0 , "待付款" ), PAID(1 , "已付款" ), WAITING_DELIVER(2 , "待发货" ), WAITING_RECEIVE(3 , "待收货" ), FINISHED(4 , "已完成" ), CANCELED(5 , "已取消" ); @EnumValue private final int code; @JsonValue private final String message; OrderStatusEnums(int code, String message) { this .code = code; this .message = message; } public static OrderStatusEnums fromDbCode (String dbCode) { for (OrderStatusEnums orderStatusEnums : values()) { if (orderStatusEnums.code == Integer.parseInt(dbCode) || orderStatusEnums.name().equals(dbCode)) { return orderStatusEnums; } } throw new IllegalArgumentException ("Unknown color code: " + dbCode); } }
2、枚举类处理方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.order.enums.handler;import com.alibaba.druid.util.StringUtils;import com.order.enums.OrderStatusEnums;import org.apache.ibatis.type.BaseTypeHandler;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.MappedJdbcTypes;import org.apache.ibatis.type.MappedTypes;import org.springframework.stereotype.Component;import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;@Component @MappedTypes(OrderStatusEnums.class) @MappedJdbcTypes(value = JdbcType.INTEGER, includeNullJdbcType = true) public class OrderStatusEnumsTypeHandler extends BaseTypeHandler <OrderStatusEnums> { @Override public void setNonNullParameter (PreparedStatement ps, int i, OrderStatusEnums parameter, JdbcType jdbcType) throws SQLException { if (parameter != null ) { ps.setString(i, String.valueOf(parameter.getCode())); } } @Override public OrderStatusEnums getNullableResult (ResultSet rs, String columnName) throws SQLException { String code = rs.getString(columnName); if (StringUtils.isEmpty(code)) { return null ; } return OrderStatusEnums.fromDbCode(code); } @Override public OrderStatusEnums getNullableResult (ResultSet rs, int columnIndex) throws SQLException { String code = rs.getString(columnIndex); if (StringUtils.isEmpty(code)) { return null ; } return OrderStatusEnums.fromDbCode(code); } @Override public OrderStatusEnums getNullableResult (CallableStatement cs, int columnIndex) throws SQLException { String code = cs.getString(columnIndex); if (StringUtils.isEmpty(code)) { return null ; } return OrderStatusEnums.fromDbCode(code); } }
3、注册到mybatis
1 2 mybatis-plus: type-handlers-package: com.order.domain.enums.handler
4、指定需要处理的属性(可选)
若无法正常转换的话,指定一下试试,我试过的情况是,自定义的类型处理器只要被扫描到,就可以生效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.order.mapper.OrderMapper" > <resultMap id ="BaseResultMap" type ="com.order.domain.Order" > <result property ="id" column ="id" jdbcType ="BIGINT" /> <result property ="userId" column ="userId" jdbcType ="BIGINT" /> <result property ="itemId" column ="itemId" jdbcType ="BIGINT" /> <result property ="amount" column ="amount" jdbcType ="INTEGER" /> <result property ="price" column ="price" jdbcType ="DECIMAL" /> <result property ="status" column ="status" jdbcType ="INTEGER" typeHandler ="com.order.enums.handler.OrderStatusEnumsTypeHandler" /> </resultMap > <sql id ="Base_Column_List" > <if test ="true" > id,user_id,item_id,amount,price,`status` </if > </sql > </mapper >
日期类异常
在搜索枚举类异常问题解决方法时,很多人都出现过日期时间类型也会报错的问题。同样也是缺少对应的处理器,可通过引入依赖解决日期相关问题。可参考参考资料3。
这个依赖中,包含了多种日期相关的类型处理器。
此依赖是直接加入到了mybatis的类型处理中,所以无需额外配置即可生效。
1 2 3 4 5 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-typehandlers-jsr310</artifactId > <version > 1.0.2</version > </dependency >
数据源不能为空异常
对于无需直接访问数据库的服务,作为入口分布式调用入口,会出现数据源不能为空的错误,所以需要在启动类中排除对应的自动装配,参考资料4。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @EnableFeignClients(basePackages = "com.business.feign", defaultConfiguration = DefaultFeignConfig.class) @EnableDiscoveryClient @SpringBootApplication(exclude={DataSourceAutoConfiguration.class, SpringBootConfiguration.class}) public class BusinessApplication { public static void main (String[] args) { SpringApplication.run(BusinessApplication.class, args); } }
备注
若可以的话,更推荐使用sharding-jdbc4.1.1的spring starter。因为这个为了解决与seata整合时出现的问题使用的解决方法不是很推荐,像deepseek说在自己项目里创建与sharding依赖内的包相同容易产生违反开源协议的问题。若不是必须要用sharding5.x版本的新特性的话,更推荐4.1.1版本,详情查看4.1.1版本的整合记录。
参考资料:
Shardingsphere-jdbc整合Feign、Seata AT 模式实现分布式事务的解决方案
整合sharding jdbc查询时,枚举类型出错
sharding-jdbc 出现 java.sql.SQLFeatureNotSupportedException: getObject with type 异常处理
sharding-jdbc Data sources cannot be empty.