error
Mybatis-Plus (MP for short) is an enhancement tool of Mybatis. On the basis of Mybatis, it only enhances and does not change, simplifying the development efficiency. In fact, it encapsulates some simple CURD methods that can be called without having to rewrite simple SQL statements, similar to JPA.
Two days ago, I created a new project, mybatis is used for the persistence layer framework, and myBatis -Plus is introduced as an enhancement tool. After the project started, I found an error when calling the interface, and the warning of error is as follows:
The error message is “invalid binding statement”, the error is the operation of the SQL statement method, from the Internet to check the answer, the error is mainly the data source binding configuration problem, so I quickly find out, from the configuration of the data source start.
To find the reason
Since the project was to separate reads and writes from multiple data sources, I integrated the dynamic configuration of data sources into a class called DataSourceConfig. Here is the code for this class:
@Configuration
@MapperScan(basePackages = "com.xjt.proxy.mapper", sqlSessionTemplateRef = "sqlTemplate"Public class DataSourceConfig {/** */ @bean@configurationProperties (prefix ="spring.datasource.master")
public DataSource masterDb() {
returnDruidDataSourceBuilder.create().build(); } /** */ @bean@configurationProperties (prefix ="spring.datasource.slave")
public DataSource slaveDb() {
returnDruidDataSourceBuilder.create().build(); } @qualifier (@qualifier) @qualifier (@qualifier) @qualifier (@qualifier)"masterDb") DataSource masterDataSource,
@Autowired(required = false) @Qualifier("slaveDb") DataSource slaveDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DynamicDataSourceEnum.MASTER.getDataSourceName(), masterDataSource);
if(slaveDataSource ! = null) { targetDataSources.put(DynamicDataSourceEnum.SLAVE.getDataSourceName(), slaveDataSource); } dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(masterDataSource);return dynamicDataSource;
}
@Bean
public SqlSessionFactory sessionFactory(@Qualifier("dynamicDb") DataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*Mapper.xml"));
bean.setDataSource(dynamicDataSource);
return bean.getObject();
}
@Bean
public SqlSessionTemplate sqlTemplate(@Qualifier("sessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean(name = "dataSourceTx")
public DataSourceTransactionManager dataSourceTx(@Qualifier("dynamicDb") DataSource dynamicDataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dynamicDataSource);
returndataSourceTransactionManager; }}Copy the code
The main content is to configure the data source mapping for the master/slave library and inject the data source into the SqlSessionFactory object. If you are confused about this part of the code or the separation of read and write, you can see my previous article “Is reading and writing separation difficult? Springboot and AOP are easy to implement.”
The sessionFactory method, which returns an SqlSessionFactory object, This object is returned by creating a new SqlSessionFactoryBean object and injecting it into the data source. The problem should be with the SqlSessionFactoryBean class. Here should be replaced with mybatis – plus another Bean in the factory class, called MybatisSqlSessionFactoryBean, opens at the source, only to find that the class is just copy the SqlSessionFactoryBean, And rewrote its own custom loading method, buildSqlSessionFactory,
If you jump to the source code of this method, you will find that there is an important piece of code in it. If this step is missing in the configuration, the injection will fail.
changes
That is to say, the injection source place also need to configure the mapper scanning path, thus, is clear about the changes in place, the place is injected into the data source SqlSessionFactoryBean after changing MybatisSqlSessionFactoryBean, The sessionFactory method is changed to the following code:
@Bean
public SqlSessionFactory sessionFactory(@Qualifier("dynamicDb") DataSource dynamicDataSource) throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
Copy the code
This way, you can start the project again and operate the SQL statements normally.