spring boot 多数据源造成 mybatis xml文件报 rg.apache.ibatis.binding.BindingException: Invalid bound statement
在配置springboot 多数据源是重新定义了DataSource ,SqlSessionFactory等类,配置如下
/** * 配置数据源 * @return */ @Bean(name = "videoDataSource") @ConfigurationProperties(prefix = "spring.datasource.db1") @Primary public DataSource videoDataSource(){ return DataSourceBuilder.create().build(); } /** * 配置SqlSessionFactory * @param dataSource * @return * @throws Exception */ @Bean(name = "videoSqlSessionFactory") @Primary public SqlSessionFactory videoSqlSessionFactory(@Qualifier("videoDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); return sqlSessionFactoryBean.getObject(); } @Bean(name = "videoTransactionManager") @Primary public DataSourceTransactionManager videoTransactionManager(@Qualifier("videoDataSource") DataSource dataSource){ return new DataSourceTransactionManager(dataSource); } @Bean(name = "videoSqlSessionTemplate") @Primary public SqlSessionTemplate videoSqlSessionTemplate(@Qualifier("videoSqlSessionFactory") SqlSessionFactory sqlSessionFactory){ return new SqlSessionTemplate(sqlSessionFactory); } @Bean(name = "videoJdbcTemplate") public JdbcTemplate videoJdbcTemplate(@Qualifier("videoDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); }
mapper文件如下
public interface CCVideoMapper { /** * 获取视频类型 * @return */ List<Map<String,Object>> getVideoType(); /** * 根据视频类型获取视频id * @param videoType * @return */ List<Map<String,Object>> getVideoIdsByVideoType(String videoType); /** * 获取学校列表 * @param schoolName * @param schoolId * @return */ List<Map<String,Object>> getSchoolList(@Param("schoolName") String schoolName, @Param("schoolId") String schoolId); /** * 查询视频权限是否存在 * @param schoolRoleId * @param schoolId * @return */ List<Map<String,Object>> getSchoolRoleMapping(@Param("schoolRoleId") String schoolRoleId, @Param("schoolId") String schoolId); /** * 增加视频权限内容 * @param videoFileId * @param schoolId * @return */ int insertCCSchoolFileLimits(@Param("videoFileId") String videoFileId, @Param("schoolId") String schoolId); List<Map<String,Object>> selectCCSchoolFileLimits(@Param("videoFileId") String videoFileId, @Param("schoolId") String schoolId); }
service
控制器
在这些代码都编写完成以后,把以前的jdbc的代码写进mybatis的xml文件中,一直报rg.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 这个错误,检查了一遍xml、配置文件均没问题,经过代码源码的排查,最后锁定在
MybatisAutoConfiguration这个类,有一个创建SqlSessionFactory 方法
@Bean @ConditionalOnMissingBean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } 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 (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.typeHandlers)) { factory.setTypeHandlers(this.typeHandlers); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } Set<String> factoryPropertyNames = Stream .of(new BeanWrapperImpl(SqlSessionFactoryBean.class).getPropertyDescriptors()).map(PropertyDescriptor::getName) .collect(Collectors.toSet()); Class<? extends LanguageDriver> defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) { // Need to mybatis-spring 2.0.2+ factory.setScriptingLanguageDrivers(this.languageDrivers); if (defaultLanguageDriver == null && this.languageDrivers.length == 1) { defaultLanguageDriver = this.languageDrivers[0].getClass(); } } if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) { // Need to mybatis-spring 2.0.2+ factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver); } return factory.getObject(); }
其中
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } 增加mapper文件的配置,而我们重写了SqlSessionFactory ,这段代码不存在,所以怎么配置也没有扫描到xml文件
在数据源配置那里加上
/*//设置mybatis的主配置文件 记住是主配置文件啊 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource mybatisXml = resolver.getResource("classpath:mybatis/mybatis-config.xml"); sqlSessionFactoryBean.setConfigLocation(mybatisXml); //设置mapper.xml文件的路径*/ // Resource [] resource = resolver.getResources("classpath*:mybatis/mapper/**/*.xml");//{resourceMapXML}; // sqlSessionFactoryBean.setMapperLocations(resource);
便可以解决这个问题