1. 程式人生 > >springboot+mybaits-plus 多資料來源+事務操作(親測有效)

springboot+mybaits-plus 多資料來源+事務操作(親測有效)

乾貨

配置檔案


@Configuration
@MapperScan({ "com.cn.springboot.*.mapper**"})
public class DynamicDataSourceConfig {
    /**
     * 在方法上註解configurationProperties時,將會把屬性注入到返回結果的bean中
     */
    @ConfigurationProperties(prefix = "spring.datasource.first")
    @Bean(name = "firstDatasource")
    @Primary
    public DruidDataSource firstDatasource() throws SQLException {
        return new DruidDataSource();
    }
    /**
     * 在方法上註解configurationProperties時,將會把屬性注入到返回結果的bean中
     */
    @ConfigurationProperties(prefix = "spring.datasource.second")
    @Bean(name = "secondDatasource")
    public DruidDataSource secondDatasource() throws SQLException {
        return new DruidDataSource();
    }

    @Bean(name = "datasource")
    public DynamicDataSource  dynamicDataSource(@Qualifier(value = "firstDatasource") DataSource firstDatasource,
            @Qualifier(value = "secondDatasource") DataSource secondDatasource) {
        DynamicDataSource bean = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("firstDatasource", firstDatasource);
        targetDataSources.put("secondDatasource", secondDatasource);
        bean.setTargetDataSources(targetDataSources);
        bean.setDefaultTargetDataSource(firstDatasource);
        return bean;
    }
    @Bean(name = "sqlSessionFactory")
    @ConfigurationProperties(prefix = "mybatis-plus")
    public SqlSessionFactory sqlSessionFactory(
            @Qualifier(value = "datasource") DynamicDataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        
        return bean.getObject();
    }
          /**
     * 事務配置,考慮多資料來源情況下 ,這個加了反而事務不起效
     * @return
     */
//    @Bean
//    public PlatformTransactionManager txManager(@Qualifier(value = "datasource") DynamicDataSource dataSource) {
//        return new DataSourceTransactionManager(dataSource);
//    }
}

package com.cn.springboot.config.mybaits1;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{
    /**
    * 取得當前使用哪個資料來源
    *
    * @return
    */
    @Override
    protected Object determineCurrentLookupKey(){
    return DbContextHolder.getDbType();
    }
}
 

package com.cn.springboot.config.mybaits1;

public enum DBTypeEnum {
    FIRSTDATASOURCE("firstDataSource"), SECONDDATASOURCE("secondDataSource");
    private String value;

    DBTypeEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

package com.cn.springboot.config.mybaits1;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Order(-100) //這是為了保證AOP在事務註解之前生效,Order的值越小,優先順序越高
public class DataSourceInterceptor {
    Logger logger = LoggerFactory.getLogger(DataSourceInterceptor.class);

    @Pointcut(value = "execution(public * com.cn.springboot.first.service..*.*(..))")
    private void firstServicePointcut() {
    };

    @Pointcut(value = "execution(public * com.cn.springboot.second.service..*.*(..))")
    private void secondServicePointcut() {
    };

    /**
     * 切換資料來源1
     */
    @Before("firstServicePointcut()")
    public void firstDataSourceInterceptor() {
        logger.debug("切換到資料來源{}..............................", "firstDataSource");
        DbContextHolder.setDbType(DBTypeEnum.FIRSTDATASOURCE);
    }

    /**
     * 切換資料來源2
     */
    @Before("secondServicePointcut()")
    public void secondDataSourceInterceptor() {
        logger.debug("切換到資料來源{}.......................", "secondDataSource");
        DbContextHolder.setDbType(DBTypeEnum.SECONDDATASOURCE);
    }
}

package com.cn.springboot.config.mybaits1;

import javax.sql.DataSource;

import org.springframework.beans.factory.InitializingBean;

public final class DataSourceBeanWrapper<T extends DataSource> implements InitializingBean {

    private T dataSource;

    public DataSourceBeanWrapper(T realDataSource) {
        super();
        this.dataSource = realDataSource;
    }

    public T getDataSource() {
        return dataSource;
    }

    public void setDataSource(T dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (this.dataSource == null) {
            throw new IllegalArgumentException("Property 'dataSources' is required");
        }
        if (this.dataSource instanceof InitializingBean) {
            ((InitializingBean) dataSource).afterPropertiesSet();
        }
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("DataSourceBeanWrapper =");
        builder.append(getClass().getName() + "@" + Integer.toHexString(hashCode()));
        builder.append("; dataSource=");
        builder.append(dataSource);
        return builder.toString();
    }
}
 

logging.path=/user/local/log
logging.level.com.cn.springboot=DEBUG
logging.level.org.springframework.web=INFO

spring.datasource.type = com.alibaba.druid.pool.DruidDataSource

#----DS1----
spring.datasource.first.driver-class-name = 
spring.datasource.first.url = 
spring.datasource.first.username = 
spring.datasource.first.password = 

#----DS2---
spring.datasource.second.druid.driver-class-name = com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.second.url =
spring.datasource.second.username = 
spring.datasource.second.password = 

#---------------------------------------------------------------------------------------

spring.datasource.druid.initial-size = 5

spring.datasource.druid.max-active = 20

spring.datasource.druid.min-idle = 5

spring.datasource.druid.max-wait= 30000

#\u4EE5\u4E0A\u4E3A\u6700\u57FA\u672C\u914D\u7F6E\u3002
#\u6CE8\uFF1Adruid\u5982\u679C\u4E0D\u914D\u7F6EFilter,\u9ED8\u8BA4\u662F\u5F00\u542F\u7684\uFF0C\u8B6C\u5982web-stat-filter\u3001stat-view-servlet\u7B49\uFF0C\u53EF\u4EE5\u901A\u8FC7\u914D\u7F6E\u5C5E\u6027\u8986\u76D6\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u4F8B\u5982\uFF1A

# WebStatFilter monitor

spring.datasource.druid.web-stat-filter.enabled=true

spring.datasource.druid.web-stat-filter.url-pattern= \*

spring.datasource.druid.web-stat-filter.exclusions= *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*

spring.datasource.druid.web-stat-filter.session-stat-enable= false

spring.datasource.druid.web-stat-filter.session-stat-max-count= 1000

spring.datasource.druid.web-stat-filter.profile-enable=true


# StatViewServlet ,it configs who can visit

spring.datasource.druid.stat-view-servlet.enabled= true

spring.datasource.druid.stat-view-servlet.url-pattern= /druid/*

spring.datasource.druid.stat-view-servlet.reset-enable= true

spring.datasource.druid.stat-view-servlet.login-username= admin

spring.datasource.druid.stat-view-servlet.login-password= admin123

spring.datasource.druid.stat-view-servlet.allow= 127.0.0.1


#mybatis-plus
#mapper
#mapper.xml路徑
# 如果是放在src/main/java目錄下 classpath:/com/yourpackage/*/mapper/*Mapper.xml
# 如果是放在resource目錄 classpath:/mapper/*Mapper.xm
mybatis-plus.mapper-locations=classpath*:/mapper/*Mapper.xml
#\u5B9E\u4F53
mybatis-plus.typeAliasesPackage=com.cn.springboot.*.entity


#主鍵型別  0:"資料庫ID自增", 1:"使用者輸入ID",2:"全域性唯一ID (數字型別唯一ID)", 3:"全域性唯一ID UUID";
mybatis-plus.global-config.id-type=0
#欄位策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷"
mybatis-plus.global-config.field-strategy=2
#駝峰下劃線轉換
mybatis-plus.global-config.db-column-underline=true
 #重新整理mapper 除錯神器
mybatis-plus.global-config.refresh-mapper: true
#資料庫大寫下劃線轉換
#mybatis-plus.global-config.capital-mode: true
#序列介面實現類配置
#mybatis-plus.global-config.key-generator: com.baomidou.springboot.xxx
#邏輯刪除配置(下面3個配置)
mybatis-plus.global-config.logic-delete-value: 0
mybatis-plus.global-config.logic-not-delete-value: 1
#自定義SQL注入器
#mybatis-plus.global-config.sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
#自定義填充策略介面實現
#mybatis-plus.global-config.meta-object-handler: com.baomidou.springboot.xxx
#開啟駝峰轉換
mybatis-plus.configuration.mapUnderscoreToCamelCase: true
mybatis-plus.configuration.cache-enabled: false