Spring boot + MyBatis,多个数据源和映射器(java 和 xml),出现"Invalid bound statement (not found)"错误



我正在尝试创建一个maven项目,以访问具有多个数据源配置的Oracle数据库。这是我的代码:

第一个数据源配置:

package com.business.data.datasource;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@Configuration
public class FirstDbConfig {

@Primary
@Bean(name = "firstDataSourceProperties")
@ConfigurationProperties("first.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}

@Primary
@Bean(name = "firstDataSource")
@ConfigurationProperties(prefix = "first.datasource")
public DataSource dataSource(@Qualifier("firstDataSourceProperties") DataSourceProperties properties) {
return DataSourceBuilder.create().build();
}

@Bean(name = "firstSessionFactory")
@Primary
public SqlSessionFactoryBean firstSessionFactory(@Qualifier("firstDataSource") final DataSource firstDataSource)
throws Exception {

final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(firstDataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:./mapper/FirstDbMapper.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.business.data.model");
return sqlSessionFactoryBean;
}
}

第二个数据源配置:

package com.business.data.datasource;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
@Configuration
public class SecondDbConfig {

@Primary
@Bean(name = "secondDataSourceProperties")
@ConfigurationProperties("second.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}

@Bean(name = "secondDataSource")
@ConfigurationProperties(prefix = "second.datasource")
public DataSource dataSource(@Qualifier("secondDataSourceProperties") DataSourceProperties properties) {
return DataSourceBuilder.create().build();
}

@Bean(name = "secondSessionFactory")
public SqlSessionFactoryBean secondSessionFactory(@Qualifier("secondDataSource") final DataSource firstDataSource)
throws Exception {

final SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(firstDataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:./mapper/SecondDbMapper.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.business.data.model");
return sqlSessionFactoryBean;
}
}

第一个映射器接口:

package com.business.data.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.business.data.model.PersonDetail;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface FirstDbMapper {    
public List<PersonDetail> getUserData(@Param("firstName") String firstName, @Param("lastName") String lastName);
}

第二个映射器接口:

package com.business.data.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.business.data.model.PersonDetail;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface SecondDbMapper {   
public List<PersonDetail> getStaffData(@Param("firstName") String firstName, @Param("lastName") String lastName);
}

src/main/resources/mapper/FirstMapper.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace must indicate mapper interface full package path . It is an alias here-->    
<mapper namespace = "com.business.data.repository.FirstDbMapper">

<select id = "getUserData" parameterType = "map" resultMap = "personDetailMap">
SELECT  *
FROM    user
WHERE UPPER(first_name) LIKE UPPER(#{firstName}||'%')
AND UPPER(last_name) LIKE UPPER(#{lastName}||'%')
</select>

...
</mapper>

src/main/resources/mapper/SecondMapper.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace must indicate mapper interface full package path . It is an alias here-->    
<mapper namespace = "com.business.data.repository.SecondDbMapper">

<select id = "getStaffData" parameterType = "map" resultMap = "personDetailMap">
SELECT  *
FROM    staff
WHERE UPPER(first_name) LIKE UPPER(#{firstName}||'%')
AND UPPER(last_name) LIKE UPPER(#{lastName}||'%')
</select>

...
</mapper>

服务等级类似

@Autowired 
FirstDbMapper firstDbMapper;
public List<PersonDetail> getUser(String fName, String lName) throws MyServiceException {
... 
try {

userList = firstDbMapper.getUserData(fName, lName); 

} catch (Exception e) {
...  
}
return userList;
}

application.properties:

first.datasource.jdbc-url=jdbc:oracle:thin:@host01:1561:db1
first.datasource.username=user1
first.datasource.password=password1
second.datasource.jdbc-url=jdbc:oracle:thin:@host02:1561:db2
second.datasource.username=user2
second.datasource.password=password2

我的春季启动应用程序java中还有@MapperScan("com.business.data.repository"(。

我只能让一个数据源工作,那就是带有@Primary注释的数据源。我在两个配置之间交换了@Primary,总是一个有@Primary的配置有效,另一个得到了";无效绑定语句(未找到(";错误

有人能帮我吗?

谢谢!

您可以在配置类上使用@MapperScan注释将映射器附加到不同的会话工厂。我发现把映射器放在不同的包中很方便,比如

@MapperScan(basePackages="mapper.package1", sqlSessionFactoryRef="firstSessionFactory")
@MapperScan(basePackages="mapper.package2", sqlSessionFactoryRef="secondSessionFactory")

使用HikariDataSource解决了该问题。

@Primary
@Bean(name = FIRST_DATASOURCE)
@ConfigurationProperties(prefix = "first.datasource")
public DataSource dataSourceFirst() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}

最新更新