ruoyi诺依框架集成mybatisplus+atomikos分布式事务,解决pagehelper失效

本项目是ruoyi的分离版,官网只有mybatis+atomikos,本文用于集成mybatisplus+atomikos,已用于实际项目中,不同环境依赖包版本不一致可能需要自行修改。

1、maven

 common中引入mybatisplus,framework中引入atomikos
		<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--分布式事务-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>

2、修改admin下yml的数据源相关配置

注意添加user,uniqueResourceName
# 数据源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://192.168.1.111:3306/db0
        username: root
        user: root
        password: 123456
        uniqueResourceName: MASTER
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:  jdbc:mysql://192.168.1.111:3306/db1
        username: root
        user: root
        password: 123456
        uniqueResourceName: SLAVE
      # 电商数据源
      ds:
        # 从数据源开关/默认关闭
        enabled: true
        url: jdbc:mysql://192.168.1.111:3306/db3
        username: root
        user: root
        password: 123456
        uniqueResourceName: DS
        

3、修改framework中DruidConfig类

package com.wms.framework.config;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import com.wms.common.enums.DataSourceType;
import com.wms.common.utils.spring.SpringUtils;
import com.wms.framework.config.properties.DruidProperties;
import com.wms.framework.datasource.DynamicDataSource;

/**
 * druid 配置多数据源
 * 
 * @author ruoyi
 */
@Configuration
public class DruidConfig
{
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slaveDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.ds")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.ds", name = "enabled", havingValue = "true")
    public DataSource dsDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
        setDataSource(targetDataSources, DataSourceType.DS.name(), "dsDataSource");
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }
    
    /**
     * 设置数据源
     * 
     * @param targetDataSources 备选数据源集合
     * @param sourceName 数据源名称
     * @param beanName bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
    {
        try
        {
            DataSource dataSource = SpringUtils.getBean(beanName);
            targetDataSources.put(sourceName, dataSource);
        }
        catch (Exception e)
        {
        }
    }

    /**
     * 去除监控页面底部的广告
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
    {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // 创建filter进行过滤
        Filter filter = new Filter()
        {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
            {
            }
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException
            {
                chain.doFilter(request, response);
                // 重置缓冲区,响应头不会被重置
                response.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换banner, 除去底部的广告信息
                text = text.replaceAll("
"
, ""); text = text.replaceAll("powered.*?shrek.wang", ""); response.getWriter().write(text); } @Override public void destroy() { } }; FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(filter); registrationBean.addUrlPatterns(commonJsPattern); return registrationBean; } }

4、修改common中的数据源枚举类

package com.wms.common.enums;

import com.wms.common.annotation.DataSource;
import lombok.Getter;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 数据源
 * 
 * @author ruoyi
 */
public enum DataSourceType
{
    /**
     * 主库
     */
    MASTER("MASTER"),

    /**
     * 从库
     */
    SLAVE("SLAVE"),

    /**
     * 电商
     */
    DS("DS");


    @Getter
    private String value;

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

    public static List<DataSourceType> getSlaveList() {
        return Arrays.asList(SLAVE, DS);
    }

    /**
     * 根据注解获取数据源
     *
     * @param dataSource
     * @return
     */
    public static DataSourceType getDataSourceKey(DataSource dataSource) {
        if (dataSource == null) {
            return MASTER;
        }
        if (dataSource.value() == DataSourceType.SLAVE) {
            List<DataSourceType> dataSourceKeyList = DataSourceType.getSlaveList();
            // FIXME 目前乱序
            Collections.shuffle(dataSourceKeyList);
            return dataSourceKeyList.get(0);
        } else {
            return dataSource.value();
        }
    }

}

5、framework下配置文件的修改改动

aspectj包下新增DataSourceAspectPlus类
package com.wms.framework.aspectj;

import com.wms.common.annotation.DataSource;
import com.wms.common.enums.DataSourceType;
import com.wms.framework.datasource.DynamicDataSourceContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Method;


@Component
@Slf4j
@Aspect
@Order(-1)
public class DataSourceAspectPlus  {

    @Pointcut("execution(* com.wms.*.dao.*Mapper.*(..))||execution(* com.baomidou.mybatisplus.core.mapper.*Mapper.*(..)))")
    public void pointCut() {
    }
    @Around("pointCut()")
    public Object doBefore(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        DataSource dataSource = AnnotationUtils.findAnnotation(method, DataSource.class);
        DataSourceType keyEnum = DataSourceType.getDataSourceKey(dataSource);
        log.info("选择的数据源:"+keyEnum.getValue());
        DynamicDataSourceContextHolder.setDataSourceType(keyEnum.getValue());
        Object o=pjp.proceed();
        DynamicDataSourceContextHolder.clearDataSourceType();
        return o;
    }
    @Pointcut("execution(* com.baomidou.mybatisplus.extension.service.IService.*Batch*(..)))")
    public void pointCutBatch() {
    }
    //对mybatisplus批量操作切面
    @Around("pointCutBatch()")
    public Object doBeforeBatch(ProceedingJoinPoint pjp) throws Throwable {
        DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.getValue());
        Object o = pjp.proceed();
        DynamicDataSourceContextHolder.clearDataSourceType();
        return o;
    }
}

datasource包下新增DynamicSqlSessionTemplate

package com.wms.framework.datasource;

import static java.lang.reflect.Proxy.newProxyInstance;
import static org.apache.ibatis.reflection.ExceptionUtil.unwrapThrowable;
import static org.mybatis.spring.SqlSessionUtils.closeSqlSession;
import static org.mybatis.spring.SqlSessionUtils.getSqlSession;
import static org.mybatis.spring.SqlSessionUtils.isSqlSessionTransactional;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.MyBatisExceptionTranslator;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.dao.support.PersistenceExceptionTranslator;


/**
 * 自定义SqlSessionTemplate,动态切换数据源
 *
 * @author ruoyi
 */
public class DynamicSqlSessionTemplate extends SqlSessionTemplate
{
    private final SqlSessionFactory sqlSessionFactory;
    private final ExecutorType executorType;
    private final SqlSession sqlSessionProxy;
    private final PersistenceExceptionTranslator exceptionTranslator;
    private Map<String, SqlSessionFactory> targetSqlSessionFactorys;
    private SqlSessionFactory defaultTargetSqlSessionFactory;

    public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory)
    {
        this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
    }

    public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType)
    {
        this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(
                sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
    }

    public DynamicSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
                                     PersistenceExceptionTranslator exceptionTranslator)
    {
        super(sqlSessionFactory, executorType, exceptionTranslator);
        this.sqlSessionFactory = sqlSessionFactory;
        this.executorType = executorType;
        this.exceptionTranslator = exceptionTranslator;
        this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
                new Class[] { SqlSession.class }, new DynamicSqlSessionTemplate.SqlSessionInterceptor());
        this.defaultTargetSqlSessionFactory = sqlSessionFactory;
    }

    public void setTargetSqlSessionFactorys(Map<String, SqlSessionFactory> targetSqlSessionFactorys)
    {
        this.targetSqlSessionFactorys = targetSqlSessionFactorys;
    }

    public void setDefaultTargetSqlSessionFactory(SqlSessionFactory defaultTargetSqlSessionFactory)
    {
        this.defaultTargetSqlSessionFactory = defaultTargetSqlSessionFactory;
    }

    @Override
    public SqlSessionFactory getSqlSessionFactory()
    {
        SqlSessionFactory targetSqlSessionFactory = targetSqlSessionFactorys
                .get(DynamicDataSourceContextHolder.getDataSourceType());
        if (targetSqlSessionFactory != null)
        {
            return targetSqlSessionFactory;
        }
        else if (defaultTargetSqlSessionFactory != null)
        {
            return defaultTargetSqlSessionFactory;
        }
        return this.sqlSessionFactory;
    }

    @Override
    public Configuration getConfiguration()
    {
        return this.getSqlSessionFactory().getConfiguration();
    }

    public ExecutorType getExecutorType()
    {
        return this.executorType;
    }

    public PersistenceExceptionTranslator getPersistenceExceptionTranslator()
    {
        return this.exceptionTranslator;
    }

    /**
     * {@inheritDoc}
     */
    public <T> T selectOne(String statement)
    {
        return this.sqlSessionProxy.<T> selectOne(statement);
    }

    /**
     * {@inheritDoc}
     */
    public <T> T selectOne(String statement, Object parameter)
    {
        return this.sqlSessionProxy.<T> selectOne(statement, parameter);
    }

    /**
     * {@inheritDoc}
     */
    public <K, V> Map<K, V> selectMap(String statement, String mapKey)
    {
        return this.sqlSessionProxy.<K, V> selectMap(statement, mapKey);
    }

    /**
     * {@inheritDoc}
     */
    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey)
    {
        return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey);
    }

    /**
     * {@inheritDoc}
     */
    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds)
    {
        return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey, rowBounds);
    }

    /**
     * {@inheritDoc}
     */
    public <E> List<E> selectList(String statement)
    {
        return this.sqlSessionProxy.<E> selectList(statement);
    }

    /**
     * {@inheritDoc}
     */
    public <E> List<E> selectList(String statement, Object parameter)
    {
        return this.sqlSessionProxy.<E> selectList(statement, parameter);
    }

    /**
     * {@inheritDoc}
     */
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds)
    {
        return this.sqlSessionProxy.<E> selectList(statement, parameter, rowBounds);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("rawtypes")
    public void select(String statement, ResultHandler handler)
    {
        this.sqlSessionProxy.select(statement, handler);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("rawtypes")
    public void select(String statement, Object parameter, ResultHandler handler)
    {
        this.sqlSessionProxy.select(statement, parameter, handler);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("rawtypes")
    public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler)
    {
        this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
    }

    /**
     * {@inheritDoc}
     */
    public int insert(String statement)
    {
        return this.sqlSessionProxy.insert(statement);
    }

    /**
     * {@inheritDoc}
     */
    public int insert(String statement, Object parameter)
    {
        return this.sqlSessionProxy.insert(statement, parameter);
    }

    /**
     * {@inheritDoc}
     */
    public int update(String statement)
    {
        return this.sqlSessionProxy.update(statement);
    }

    /**
     * {@inheritDoc}
     */
    public int update(String statement, Object parameter)
    {
        return this.sqlSessionProxy.update(statement, parameter);
    }

    /**
     * {@inheritDoc}
     */
    public int delete(String statement)
    {
        return this.sqlSessionProxy.delete(statement);
    }

    /**
     * {@inheritDoc}
     */
    public int delete(String statement, Object parameter)
    {
        return this.sqlSessionProxy.delete(statement, parameter);
    }

    /**
     * {@inheritDoc}
     */
    public <T> T getMapper(Class<T> type)
    {
        return getConfiguration().getMapper(type, this);
    }

    /**
     * {@inheritDoc}
     */
    public void commit()
    {
        throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    }

    /**
     * {@inheritDoc}
     */
    public void commit(boolean force)
    {
        throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
    }

    /**
     * {@inheritDoc}
     */
    public void rollback()
    {
        throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    }

    /**
     * {@inheritDoc}
     */
    public void rollback(boolean force)
    {
        throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
    }

    /**
     * {@inheritDoc}
     */
    public void close()
    {
        throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
    }

    /**
     * {@inheritDoc}
     */
    public void clearCache()
    {
        this.sqlSessionProxy.clearCache();
    }

    /**
     * {@inheritDoc}
     */
    public Connection getConnection()
    {
        return this.sqlSessionProxy.getConnection();
    }

    /**
     * {@inheritDoc}
     *
     * @since 1.0.2
     */
    public List<BatchResult> flushStatements()
    {
        return this.sqlSessionProxy.flushStatements();
    }

    /**
     * Proxy needed to route MyBatis method calls to the proper SqlSession got from Spring's Transaction Manager It also
     * unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to pass a {@code PersistenceException} to
     * the {@code PersistenceExceptionTranslator}.
     */
    private class SqlSessionInterceptor implements InvocationHandler
    {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            final SqlSession sqlSession = getSqlSession(DynamicSqlSessionTemplate.this.getSqlSessionFactory(),
                    DynamicSqlSessionTemplate.this.executorType, DynamicSqlSessionTemplate.this.exceptionTranslator);
            try
            {
                Object result = method.invoke(sqlSession, args);
                if (!isSqlSessionTransactional(sqlSession, DynamicSqlSessionTemplate.this.getSqlSessionFactory()))
                {
                    sqlSession.commit(true);
                }
                return result;
            }
            catch (Throwable t)
            {
                Throwable unwrapped = unwrapThrowable(t);
                if (DynamicSqlSessionTemplate.this.exceptionTranslator != null
                        && unwrapped instanceof PersistenceException)
                {
                    Throwable translated = DynamicSqlSessionTemplate.this.exceptionTranslator
                            .translateExceptionIfPossible((PersistenceException) unwrapped);
                    if (translated != null)
                    {
                        unwrapped = translated;
                    }
                }
                throw unwrapped;
            }
            finally
            {
                closeSqlSession(sqlSession, DynamicSqlSessionTemplate.this.getSqlSessionFactory());
            }
        }
    }
}

config包下新增MyGlobalConfig

package com.wms.framework.config;

import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.wms.framework.datasource.DynamicSqlSessionTemplate;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class MyGlobalConfig extends GlobalConfig {

    @Autowired
    private DynamicSqlSessionTemplate sqlSessionTemplate;

    private static DynamicSqlSessionTemplate mySqlSessionTemplate;

    @Override
    public SqlSessionFactory getSqlSessionFactory() {
        return mySqlSessionTemplate.getSqlSessionFactory();
    }

    @PostConstruct
    public void init() {
        MyGlobalConfig.mySqlSessionTemplate = sqlSessionTemplate;
    }
}
config中注释MyBatisConfig.java中所有的内容,新增MybatisPlusConfig
package com.wms.framework.config;

import com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean;
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.github.pagehelper.PageInterceptor;
import com.wms.common.enums.DataSourceType;
import com.wms.common.utils.StringUtils;
import com.wms.common.utils.bean.BeanUtils;
import com.wms.common.utils.spring.SpringUtils;
import com.wms.framework.datasource.DynamicSqlSessionTemplate;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * Mybatis Plus 配置
 *
 * @author ruoyi
 */
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig
{
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public AtomikosNonXADataSourceBean userMaster() {
        //也可以直接return new AtomikosNonXADataSourceBean();
        return DataSourceBuilder.create().type(AtomikosNonXADataSourceBean.class).build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.ds")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.ds", name = "enabled", havingValue = "true")
    public AtomikosNonXADataSourceBean userSlave0() {
        return DataSourceBuilder.create().type(AtomikosNonXADataSourceBean.class).build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public AtomikosNonXADataSourceBean userSlave1() {
        return DataSourceBuilder.create().type(AtomikosNonXADataSourceBean.class).build();
    }

    @Bean(name = "sqlSessionTemplate")
    public DynamicSqlSessionTemplate customSqlSessionTemplate() throws Exception {
        Map<String, SqlSessionFactory> sqlSessionFactoryMap = new HashMap<String, SqlSessionFactory>();
        sqlSessionFactoryMap.put(DataSourceType.MASTER.getValue(),createSqlSessionFactory(userMaster()));
        try
        {
            sqlSessionFactoryMap.put(DataSourceType.DS.getValue(), createSqlSessionFactory(userSlave0()));
        }
        catch (Exception e)
        {
        }
        try
        {
            sqlSessionFactoryMap.put(DataSourceType.SLAVE.getValue(), createSqlSessionFactory(userSlave1()));
        }
        catch (Exception e)
        {
        }
        DynamicSqlSessionTemplate sqlSessionTemplate = new DynamicSqlSessionTemplate(sqlSessionFactoryMap.get(DataSourceType.MASTER.getValue()));
        sqlSessionTemplate.setTargetSqlSessionFactorys(sqlSessionFactoryMap);
        return sqlSessionTemplate;
    }

    /**
     * 创建数据源
     *
     * @param dataSource
     * @return
     */
    private SqlSessionFactory createSqlSessionFactory(AtomikosNonXADataSourceBean dataSource) throws Exception {
        dataSource.setMaxPoolSize(10);
        dataSource.setMinPoolSize(2);
        dataSource.setPoolSize(2);
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setMaxIdleTime(60);//最大闲置时间,超过最小连接池的连接将关闭
        dataSource.setMaxLifetime(1200);//连接最大闲置时间 单位s 全部的连接超时将关闭

        dataSource.setMaintenanceInterval(60);//定时维护线程周期 单位秒
        //以上配置可提取到.yml内通过ConfigurationProperties注解注入

        dataSource.init();//项目启动则初始化连接
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setTypeAliasesPackage("com.wms.**.domain");
        if(DataSourceType.DS.getValue().equals(dataSource.getUniqueResourceName())){
            sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/dsBusiness/dsBaseGoods/*Mapper.xml"));
        }else if(DataSourceType.SLAVE.getValue().equals(dataSource.getUniqueResourceName())){
            sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/business/haiguanDataWms/*Mapper.xml"));
        }else{
            sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*Mapper.xml"));
        }

        sqlSessionFactory.setVfs(SpringBootVFS.class);
        sqlSessionFactory.setPlugins(pageInterceptor());

        MybatisConfiguration configuration = new MybatisConfiguration();
        //configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(false);
        configuration.setCacheEnabled(false);
        configuration.setMapUnderscoreToCamelCase(true);
        sqlSessionFactory.setConfiguration(configuration);

        //重写了GlobalConfig的MyGlobalConfig注入到sqlSessionFactory使其生效
        MyGlobalConfig globalConfig = new MyGlobalConfig();
        sqlSessionFactory.setGlobalConfig(globalConfig);

        sqlSessionFactory.afterPropertiesSet();
        return sqlSessionFactory.getObject();
    }


    @Bean
    PageInterceptor pageInterceptor(){
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "mysql");
        pageInterceptor.setProperties(properties);  // 由此可进入源码,
        return pageInterceptor;
    }


}


注意:pageInterceptor必须要有,否则分页失效

6、使用

在业务层加入数据源注解,主库不需要加入注解,其他从库需要
@Service
@DataSource(value = DataSourceType.DS)
public class DsBaseGoodsServiceImpl extends ServiceImpl<DsBaseGoodsMapper, DsBaseGoods> implements IDsBaseGoodsService
最后,在方法是加入 @Transactional即可
    @Override
    @Transactional
    public AjaxResult addArrivalNotice(DsArrivalNoticeHead dsArrivalNoticeHead) {

        DsBaseGoods dsBaseGoods1 = new DsBaseGoods();
        dsBaseGoods1.setBaseGoodsId("3146");
        dsBaseGoods1.setWhNo("1");

        dsBaseGoodsService.updateDsBaseGoods(dsBaseGoods1);
//        List dsBaseGoods = dsBaseGoodsService.selectDsBaseGoodsList(new DsBaseGoods());
        WmsCarInfo wmsCarInfo = new WmsCarInfo();
        wmsCarInfo.setCarInfoId(IdUtils.fastSimpleUUID());
        wmsCarInfo.setDriverName("123");
        wmsCarInfoService.save(wmsCarInfo);
        //校验仓库编码是否存在
        int i =1/0;
        //判断通知单号是否已经存在

        //获取批次号

        return null;
    }

你可能感兴趣的:(分布式,mybatis,java)