MybatisPlus自定义多数据源时BaseMapper中方法(insert,selectList)遇到Invalid bound statement (not found)问题

背景:

项目使用了MybatisPlus,多数据源和shardingsphere,所以自定义了数据源配置,按照需求去生成sqlSessionFactory,就遇到了MybatisPlus原生的BaseMapper中的方法无法使用,比如insert, update, selectList之类的,都出现了Invalid bound statement 问题。

解决方法:

1,先检查一下MapperScan是否正确,注意后面这个是自定义配置才会有。

@MapperScan(basePackages = {"com.xgd.hub.account.repository.mapper"},
sqlSessionFactoryRef = "sqlSessionFactory")

2,检查一下type-aliases-package是否正确

mybatis-plus:
  configuration:
    cache-enabled: true
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:mapper/*.xml
  type-aliases-package: com.xxx.xxx.xxx.repository.entity.*

3,检查自定义的数据源配置是否正确

package com.xxx.xxx.xxx.config.datasource.dynamic;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.xxx.xxx.xxx.commons.SysConstant;
import com.xxx.xxx.xxx.config.datasource.shardingsphere.MonthShardingAlgorithm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import lombok.SneakyThrows;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * 动态数据源+分表配置(shardingsphere).
 *
 * @date 2023/11/20 16:31
 */
@Configuration
@MapperScan(basePackages = {"com.xxx.xxx.xxx.repository.mapper"},
        sqlSessionFactoryRef = "sqlSessionFactory")
public class DynamicDataSourceConfig {
    @Autowired
    private MonthShardingAlgorithm monthShardingAlgorithm;
    @Value("${spring.datasource.druid.shardings.account_trans_list_logictable}")
    private String accountTransListLogicTable;
    @Value("${spring.datasource.druid.shardings.account_trans_list_actualDataNodes}")
    private String accountTransListActualDataNodes;
    @Value("${spring.datasource.druid.shardings.account_trans_list_shardingColumn}")
    private String accountTransListShardingColumn;
    @Value("${spring.datasource.druid.shardings.account_voucher_list_logictable}")
    private String accountVoucherListLogicTable;
    @Value("${spring.datasource.druid.shardings.account_voucher_list_actualDataNodes}")
    private String accountVoucherListActualDataNodes;
    @Value("${spring.datasource.druid.shardings.account_voucher_list_shardingColumn}")
    private String accountVoucherListShardingColumn;

    /**
     * 将多个数据源添加进来.
     *
     * @param dsProperties notnull
     * @return notnull
     */
    @Bean(name = "dynamicDataSource")
    public DynamicDataSource dynamicDataSource(DataSourceProperties dsProperties) {
        Map targetDataSources = new HashMap(8);
        // 主从数据库
        targetDataSources.put(SysConstant.MASTER_DATASOURCE, dsProperties.getMaster());
        targetDataSources.put(SysConstant.SLAVE_DATASOURCE, dsProperties.getSlave());
        // shardinsphere数据库
        DataSource shardingsDataSource = buildDataSource(dsProperties);
        targetDataSources.put(SysConstant.SHARDINGS_DATASOURCE, shardingsDataSource);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        return dataSource;
    }

    /**
     * 创建动态数据源的SqlSessionFactory,传入的是动态数据源.
     * Primary 这个注解很重要,如果项目中存在多个SqlSessionFactory,这个注解一定要加上.
     */
    @Primary
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean(@Qualifier("dynamicDataSource") DynamicDataSource
                                                               dynamicDataSource) throws Exception {
        //重点,不要用原生的org.mybatis.spring.SqlSessionFactoryBean
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        //重点,不要用原生的org.apache.ibatis.session.Configuration
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setDefaultFetchSize(100);
        configuration.setDefaultStatementTimeout(30);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        sqlSessionFactoryBean.setConfiguration(configuration);
        return sqlSessionFactoryBean.getObject();
    }

    /**
     * 重写事务管理器,管理动态数据源.
     */
    @Primary
    @Bean(value = "transactionManager")
    public PlatformTransactionManager annotationDrivenTransactionManager(@Qualifier("dynamicDataSource")
                                                                             DynamicDataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * Shardingsphere数据源配置.
     *
     * @param properties notnull
     * @return notnull
     */
    @SneakyThrows
    private DataSource buildDataSource(DataSourceProperties properties) {
        Map dataSourceMap = new HashMap<>();
        dataSourceMap.put(SysConstant.SHARDINGS_DATASOURCE, properties.getShardings());
        // table rule - accountTransList
        TableRuleConfiguration accountTransListTableRule = new TableRuleConfiguration(accountTransListLogicTable,
                accountTransListActualDataNodes);
        // 分表策略 new MonthShardingAlgorithm()
        ShardingStrategyConfiguration accountTransShardingStrategyConfig = new StandardShardingStrategyConfiguration(
                accountTransListShardingColumn, monthShardingAlgorithm, monthShardingAlgorithm);
        accountTransListTableRule.setTableShardingStrategyConfig(accountTransShardingStrategyConfig);

        // table rule - accountVoucherList
        TableRuleConfiguration accountVoucherListTableRule = new TableRuleConfiguration(accountVoucherListLogicTable,
                accountVoucherListActualDataNodes);
        // 分表策略 new MonthShardingAlgorithm()
        ShardingStrategyConfiguration accountVoucherShardingStrategyConfig = new StandardShardingStrategyConfiguration(
                accountVoucherListShardingColumn, monthShardingAlgorithm, monthShardingAlgorithm);
        accountVoucherListTableRule.setTableShardingStrategyConfig(accountVoucherShardingStrategyConfig);


        // 可以添加多个不同的分表配置
        List list = new ArrayList();
        list.add(accountTransListTableRule);
        list.add(accountVoucherListTableRule);
        // 具体分库分表策略,按什么规则来分
        ShardingRuleConfiguration conf = new ShardingRuleConfiguration();
        conf.setTableRuleConfigs(list);
        Properties props = new Properties();
        props.put("sql.show", true);
        DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, conf, props);
        return dataSource;
    }
}

重点:

 //重点,不要用原生的org.mybatis.spring.SqlSessionFactoryBean
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        //重点,不要用原生的org.apache.ibatis.session.Configuration
        MybatisConfiguration configuration = new MybatisConfiguration();

你可能感兴趣的:(解决问题,数据库,多数据源,MybatisPlus,BaseMapper)