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 List
configurationCustomizers; 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列名改为小写就可以了。
等官方发新版本就可以了。 或者自己改下源码 重新打包。

上一篇:seata和postgresql和springcloud整合
下一篇:ElasicJob分布式定时任务

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年03月31日 23时34分57秒