
seata和sharding和postgresql整合
发布日期:2021-05-06 22:37:54
浏览次数:21
分类:技术文章
本文共 14565 字,大约阅读时间需要 48 分钟。
第一步导入坐标
org.postgresql postgresql runtime org.apache.shardingsphere sharding-jdbc-spring-boot-starter 4.0.0-RC2 org.apache.shardingsphere sharding-transaction-base-seata-at 4.0.0-RC2 com.baomidou mybatis-plus-boot-starter 3.2.0 com.alibaba druid-spring-boot-starter 1.1.10 com.alibaba.cloud spring-cloud-alibaba-seata 2.2.0.RELEASE io.seata seata-spring-boot-starter io.seata seata-spring-boot-starter 1.3.0
第二步增加配置类
1)MybatisPlusConfig类import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.Order;/** * mybatis-plus配置 * @author yyj */@Configurationpublic class MybatisPlusConfig { /** * 配置分页 */ @Bean @Order(0) public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } /** * 主键生成策略 * @return */ @Bean public IKeyGenerator keyGenerator(){ return new H2KeyGenerator(); }}
2)MybatisPlusAutoConfig类
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;import com.baomidou.mybatisplus.core.MybatisConfiguration;import com.baomidou.mybatisplus.core.config.GlobalConfig;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;import com.baomidou.mybatisplus.core.injector.ISqlInjector;import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.mapping.DatabaseIdProvider;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.session.ExecutorType;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.mapper.ClassPathMapperScanner;import org.mybatis.spring.mapper.MapperFactoryBean;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.BeansException;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.BeanFactoryAware;import org.springframework.beans.factory.InitializingBean;import org.springframework.beans.factory.ObjectProvider;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.boot.autoconfigure.AutoConfigurationPackages;import org.springframework.boot.autoconfigure.AutoConfigureAfter;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.ApplicationContext;import org.springframework.context.ResourceLoaderAware;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;import org.springframework.core.io.Resource;import org.springframework.core.io.ResourceLoader;import org.springframework.core.type.AnnotationMetadata;import org.springframework.util.Assert;import org.springframework.util.CollectionUtils;import org.springframework.util.ObjectUtils;import org.springframework.util.StringUtils;import javax.sql.DataSource;import java.util.Iterator;import java.util.List;/** * sharding+seata+mp整合开始 第三步配置数据源 * @author yyj * @date 2020年7月20日16:48:19 */@Configuration@AutoConfigureAfter(MybatisPlusConfig.class)@EnableConfigurationProperties({ MybatisPlusProperties.class})public class MybatisPlusAutoConfig { private static final Logger logger = LoggerFactory.getLogger(MybatisPlusAutoConfig.class); private final MybatisPlusProperties properties; private final Interceptor[] interceptors; private final ResourceLoader resourceLoader; private final DatabaseIdProvider databaseIdProvider; private final ListconfigurationCustomizers; private final ApplicationContext applicationContext; public MybatisPlusAutoConfig(MybatisPlusProperties properties, ObjectProvider interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider
> configurationCustomizersProvider, ApplicationContext applicationContext) { this.properties = properties; this.interceptors = (Interceptor[]) interceptorsProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = (DatabaseIdProvider) databaseIdProvider.getIfAvailable(); this.configurationCustomizers = (List) configurationCustomizersProvider.getIfAvailable(); this.applicationContext = applicationContext; } public void afterPropertiesSet() { this.checkConfigFileExists(); } private void checkConfigFileExists() { if (this.properties.isCheckConfigLocation() && StringUtils .hasText(this.properties.getConfigLocation())) { Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation()); Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)"); } } @Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory .setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } this.applyConfiguration(factory); if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) { factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage()); } if (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } GlobalConfig globalConfig = this.properties.getGlobalConfig(); if (this.applicationContext.getBeanNamesForType(MetaObjectHandler.class, false, false).length > 0) { MetaObjectHandler metaObjectHandler = (MetaObjectHandler) this.applicationContext .getBean(MetaObjectHandler.class); globalConfig.setMetaObjectHandler(metaObjectHandler); } if (this.applicationContext.getBeanNamesForType(IKeyGenerator.class, false, false).length > 0) { IKeyGenerator keyGenerator = (IKeyGenerator) this.applicationContext .getBean(IKeyGenerator.class); globalConfig.getDbConfig().setKeyGenerator(keyGenerator); } if (this.applicationContext.getBeanNamesForType(ISqlInjector.class, false, false).length > 0) { ISqlInjector iSqlInjector = (ISqlInjector) this.applicationContext .getBean(ISqlInjector.class); globalConfig.setSqlInjector(iSqlInjector); } factory.setGlobalConfig(globalConfig); return factory.getObject(); } private void applyConfiguration(MybatisSqlSessionFactoryBean factory) { MybatisConfiguration configuration = this.properties.getConfiguration(); if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) { configuration = new MybatisConfiguration(); } if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { Iterator var3 = this.configurationCustomizers.iterator(); while (var3.hasNext()) { ConfigurationCustomizer customizer = (ConfigurationCustomizer) var3.next(); customizer.customize(configuration); } } factory.setConfiguration(configuration); } @Bean @ConditionalOnMissingBean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { ExecutorType executorType = this.properties.getExecutorType(); return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory); } @Configuration @Import({ AutoConfiguredMapperScannerRegistrar.class}) @ConditionalOnMissingBean({ MapperFactoryBean.class}) public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean { public MapperScannerRegistrarNotFoundConfiguration() { } @Override public void afterPropertiesSet() { MybatisPlusAutoConfig.logger.debug("No {} found.", MapperFactoryBean.class.getName()); } } public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware { private BeanFactory beanFactory; private ResourceLoader resourceLoader; public AutoConfiguredMapperScannerRegistrar() { } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { if (!AutoConfigurationPackages.has(this.beanFactory)) { MybatisPlusAutoConfig.logger.debug( "Could not determine auto-configuration package, automatic mapper scanning disabled."); } else { MybatisPlusAutoConfig.logger.debug("Searching for mappers annotated with @Mapper"); List packages = AutoConfigurationPackages.get(this.beanFactory); if (MybatisPlusAutoConfig.logger.isDebugEnabled()) { packages.forEach((pkg) -> { MybatisPlusAutoConfig.logger.debug("Using auto-configuration base package '{}'", pkg); }); } ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); if (this.resourceLoader != null) { scanner.setResourceLoader(this.resourceLoader); } scanner.setAnnotationClass(Mapper.class); scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(packages)); } } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } }}
第三步排除数据源
@SpringBootApplication(exclude = { DruidDataSourceAutoConfigure.class, DataSourceAutoConfiguration.class, MybatisPlusAutoConfiguration.class})
第四步seata配置
### 这里很重要# 异常:Could not register branch into global session xid = status = Rollbacked(还有Rollbacking、AsyncCommitting等等二阶段状态) while expecting Begin# 描述:分支事务注册时,全局事务状态需是一阶段状态begin,非begin不允许注册。属于seata框架层面正常的处理,用户可以从自身业务层面解决。# 出现场景(可继续补充)## 1. 分支事务是异步,全局事务无法感知它的执行进度,全局事务已进入二阶段,该异步分支才来注册# 2. 服务a rpc 服务b超时(dubbo、feign等默认1秒超时),a上抛异常给tm,tm通知tc回滚,但是b还是收到了请求(网络延迟或rpc框架重试),然后去tc注册时发现全局事务已在回滚# 3. tc感知全局事务超时(@GlobalTransactional(timeoutMills = 默认60秒)),主动变更状态并通知各分支事务回滚,此时有新的分支事务来注册ribbon: # 连接超时 ConnectTimeout: 5000 # 响应超时 设置超时时间设置长一点。应为回滚需要时间 ReadTimeout: 10000seata: enabled: true application-id: data-api tx-service-group: my_test_tx_group enable-auto-data-source-proxy: true config: type: nacos nacos: namespace: server-addr: 192.168.101.50:8848 group: SEATA_GROUP username: nacos password: nacos registry: type: nacos nacos: application: seata-server server-addr: 192.168.101.50:8848 namespace: username: nacos password: nacos
第五步resources增加seata.conf文件
## ---------------------------------------------------------------------------## Licensed to the Apache Software Foundation (ASF) under one or more## contributor license agreements. See the NOTICE file distributed with## this work for additional information regarding copyright ownership.## The ASF licenses this file to You under the Apache License, Version 2.0## (the "License"); you may not use this file except in compliance with## the License. You may obtain a copy of the License at#### http://www.apache.org/licenses/LICENSE-2.0#### Unless required by applicable law or agreed to in writing, software## distributed under the License is distributed on an "AS IS" BASIS,## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.## See the License for the specific language governing permissions and## limitations under the License.## ---------------------------------------------------------------------------client { ##这个是唯一的和项目名称一致 application.id = data-api transaction.service.group = my_test_tx_group}
注意
seata1.3.0和sharding整合会报一个错误 Can not find columnLabel INDEX_NAME 这个问题我已经给官方修复了。只需要把ResultSet列名改为小写就可以了。 等官方发新版本就可以了。 或者自己改下源码 重新打包。发表评论
最新留言
感谢大佬
[***.8.128.20]2025年03月31日 23时34分57秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
2021年车工(高级)考试总结及车工(高级)试题及答案
2019-03-03
2021年压力焊证考试及压力焊实操考试视频
2019-03-03
2021年低压电工考试及低压电工考试申请表
2019-03-03
2021年低压电工考试及低压电工考试申请表
2019-03-03
2021年A特种设备相关管理(电梯)考试APP及A特种设备相关管理(电梯)复审考试
2019-03-03
2021年N1叉车司机考试题及N1叉车司机复审模拟考试
2019-03-03
2021年危险化学品经营单位主要负责人考试APP及危险化学品经营单位主要负责人多少钱
2019-03-03
2021年T电梯修理考试技巧及T电梯修理模拟考试软件
2019-03-03
2021年电工(初级)考试及电工(初级)证考试
2019-03-03
大数据学习之Spark——00Spark项目的pom.xml文件
2019-03-03
CodeBlocks开发wxWidgets环境配置详细
2019-03-03
天涯人脉通讯录 - 设计草图
2019-03-03
wxWidgets 最新版2.8.11,终于放出来了
2019-03-03
python学习09:暂停一秒后再输出
2019-03-03
6、ShardingSphere 之 读写分离
2019-03-03
C++ STL
2019-03-03
解方程
2019-03-03
练习赛 位运算 思维 思维
2019-03-03
Netty 粘包 拆包 | 史上最全解读
2019-03-03