繁体   English   中英

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

[英]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.

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