[英]MyBatis mapper class not registered in Spring Boot application with two datasources
我们有一个Spring Boot应用程序,该应用程序应该通过MyBatis映射器从两个不同的数据库DB2和Oracle访问存储过程
我们已经创建了两个DB2上下文类,例如针对DB2
@Configuration
@MapperScan({ "...mapper.mybatis.db2" })
public class Db2Context {
@Primary
@Bean(name = "db2DataSource")
public DataSource getDataSource() { ...
@Primary
@Bean(name = "db2SqlSessionFactory")
public SqlSessionFactory getSqlSessionFactory() {...
MyBatis豆看起来像
public interface Db2Mapper extends MyBatisMapper<SomeType> {
@Override
@Select(value = ...)
@Options(statementType = StatementType.CALLABLE)
@Results({...})
List<SomeType> select(Map<String, Object> parameters);
然后将SqlSessionFactory bean以适当的限定注入到相应的DAO类中,例如
@Repository
public class Db2Dao {
@Autowired
@Qualifier("db2SqlSessionFactory")
SqlSessionFactory sqlSessionFactory;
...
try(SqlSession session= sqlSessionFactory.openSession(true);) {
Db2Mapper mapper = session.getMapper(Db2Mapper.class);
resultSet = mapper.select(parameters);
我们也具有与Oracle相同的配置,映射器和DAO,除了在该配置中,DataSource和SqlSessionFactory bean没有使用@Primary注释。 根据Spring Boot参考资料中的描述,这是必需的: http : //docs.spring.io/spring-boot/docs/1.2.3.RELEASE/reference/htmlsingle/#howto-two-datasources ; 否则,Spring Boot应用程序启动将导致NoUniqueBeanDefinitionException
通过这种配置,Spring Boot应用程序成功启动,并且在启动过程中甚至还有INFO日志打印输出,表明已成功识别两个映射器类
INFO BeanPostProcessorChecker : Bean 'db2Mapper' of type [class org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO BeanPostProcessorChecker : Bean 'oracleMapper' of type [class org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
但是,在运行时我们遇到了问题。 首先执行Db2Dao,然后一切顺利,执行DB2存储过程,并通过Db2Mapper存储检索到的结果。 然后是OracleDao; 但是,在执行Oracle SP之后,会收到以下异常
ERROR Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed; ... Type interface com....mapper.mybatis.oracle.OracleMapper is not
known to the MapperRegistry.]
我们一直在与这个问题作斗争一段时间,但找不到解决方案。 可能使用@Primary可能与它有关,但是没有它,我们甚至无法启动应用程序。 我们的研究实际上似乎表明不同的库版本甚至可能提供不同的行为:我们的堆栈是Java 1.8,Spring Boot 1.2.6,Spring 4.1.7,MyBatis 3.2.5,MyBatis-Spring 1.2.2。
首先 ,我建议根本不要将SqlSessionFactory
自动连接到您的DAO中。 实际上,您可以完全摆脱DAO,并在服务层中将映射器用作spring bean。
因此,您可以执行以下操作:
public interface Db2Mapper extends MyBatisMapper<SomeType> {
@Override
@Select(value = ...)
@Options(statementType = StatementType.CALLABLE)
@Results({...})
List<SomeType> select(Map<String, Object> parameters);
}
@Service
public class Db2Service{
@Autowired
private Db2Mapper db2Mapper;
//...
}
其次 ,将各种数据源与mybatis-spring集成的关键是@MapperScan
批注的sqlSessionFactoryRef
属性。 这样,您可以缩小哪个SqlSessionFactory
实例用于@MapperScan
。 像这样:
@Configuration
@MapperScan(value = { "...mapper.mybatis.db2" }, sqlSessionFactoryRef = "db2SqlSessionFactory")
public class Db2Context {
@Primary
@Bean(name = "db2DataSource")
public DataSource getDataSource() { ...
@Primary
@Bean(name = "db2SqlSessionFactory")
public SqlSessionFactory getSqlSessionFactory() {...
@Configuration
@MapperScan(value = { "...mapper.mybatis.other" }, sqlSessionFactoryRef = "otherSqlSessionFactory")
public class OtherContext {
@Bean(name = "otherDataSource")
public DataSource getDataSource() { ...
@Bean(name = "otherSqlSessionFactory")
public SqlSessionFactory getSqlSessionFactory() {...
显然,您不应该使用这两个@MapperScan注释扫描相同的软件包。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.