简体   繁体   English

MyBatis映射器类未在Spring Boot应用程序中使用两个数据源注册

[英]MyBatis mapper class not registered in Spring Boot application with two datasources

We have a Spring Boot application that should access stored procedures from two different databases, DB2 and Oracle, through MyBatis mappers 我们有一个Spring Boot应用程序,该应用程序应该通过MyBatis映射器从两个不同的数据库DB2和Oracle访问存储过程

We have created two DB2 context classes, eg for DB2 我们已经创建了两个DB2上下文类,例如针对DB2

@Configuration
@MapperScan({ "...mapper.mybatis.db2" })
public class Db2Context {

  @Primary
  @Bean(name = "db2DataSource")
  public DataSource getDataSource() { ...

  @Primary
  @Bean(name = "db2SqlSessionFactory")
  public SqlSessionFactory getSqlSessionFactory() {...

The MyBatis beans look like MyBatis豆看起来像

public interface Db2Mapper extends MyBatisMapper<SomeType> {

  @Override
  @Select(value = ...)
  @Options(statementType = StatementType.CALLABLE)
  @Results({...}) 
  List<SomeType> select(Map<String, Object> parameters);

And the SqlSessionFactory beans are injected into the respective DAO classes with the appropriate qualification, eg 然后将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);

We have the identical config, mapper and DAO for Oracle as well, except that in that config the DataSource and SqlSessionFactory beans are not annotated with @Primary. 我们也具有与Oracle相同的配置,映射器和DAO,除了在该配置中,DataSource和SqlSessionFactory bean没有使用@Primary注释。 This was necessary as per described in the Spring Boot reference: http://docs.spring.io/spring-boot/docs/1.2.3.RELEASE/reference/htmlsingle/#howto-two-datasources ; 根据Spring Boot参考资料中的描述,这是必需的: http : //docs.spring.io/spring-boot/docs/1.2.3.RELEASE/reference/htmlsingle/#howto-two-datasources ; without that the Spring Boot application startup would result in NoUniqueBeanDefinitionException 否则,Spring Boot应用程序启动将导致NoUniqueBeanDefinitionException

With this configuration the Spring Boot application starts up succesfully, and during the startup there are even INFO log printouts indicating that both mapper classes have been succesfully identified 通过这种配置,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)

However, in runtime we have a problem. 但是,在运行时我们遇到了问题。 First Db2Dao is executed, and with that everything goes perfectly, the DB2 stored procedure is getting executed, and the retrieved results are stored through Db2Mapper. 首先执行Db2Dao,然后一切顺利,执行DB2存储过程,并通过Db2Mapper存储检索到的结果。 Then comes OracleDao; 然后是OracleDao; however after the Oracle SP execution the following exception is received 但是,在执行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.]

We have been fighting with this issue for some while now, but could not find a resolution. 我们一直在与这个问题作斗争一段时间,但找不到解决方案。 Possibly the usage of @Primary might have something to do with it, but without that we are not even able to start up the application. 可能使用@Primary可能与它有关,但是没有它,我们甚至无法启动应用程序。 Our researches actually seem to indicate that different library versions might even provide different behaviour: our stack is Java 1.8, Spring Boot 1.2.6, Spring 4.1.7, MyBatis 3.2.5, MyBatis-Spring 1.2.2 我们的研究实际上似乎表明不同的库版本甚至可能提供不同的行为:我们的堆栈是Java 1.8,Spring Boot 1.2.6,Spring 4.1.7,MyBatis 3.2.5,MyBatis-Spring 1.2.2。

First of all , I would suggest not to autowire SqlSessionFactory into your DAOs at all. 首先 ,我建议根本不要将SqlSessionFactory自动连接到您的DAO中。 In fact you can get rid of DAOs completely and use your mappers in service layer as spring beans. 实际上,您可以完全摆脱DAO,并在服务层中将映射器用作spring bean。

So you do something like this: 因此,您可以执行以下操作:

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;

  //...
}

Secondly , the key to have various datasources integrated with mybatis-spring is in sqlSessionFactoryRef attribute of @MapperScan annotation. 其次 ,将各种数据源与mybatis-spring集成的关键是@MapperScan批注的sqlSessionFactoryRef属性。 With that you can narrow down which SqlSessionFactory instance is used for witch @MapperScan . 这样,您可以缩小哪个SqlSessionFactory实例用于@MapperScan Something like this: 像这样:

@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() {...

Obviously you shouldn't scan same packages with these two @MapperScan annotations. 显然,您不应该使用这两个@MapperScan注释扫描相同的软件包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM