gpt4 book ai didi

java - MyBatis 映射器类未在具有两个数据源的 Spring Boot 应用程序中注册

转载 作者:行者123 更新时间:2023-11-30 03:07:17 24 4
gpt4 key购买 nike

我们有一个 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 bean 看起来像

public interface Db2Mapper extends MyBatisMapper<SomeType> {

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

并且 SqlSessionFactory bean 被注入(inject)到具有适当资格的相应 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属性。这样,您就可以缩小用于 @MapperScanSqlSessionFactory 实例的范围。像这样的事情:

@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注释扫描相同的包。

关于java - MyBatis 映射器类未在具有两个数据源的 Spring Boot 应用程序中注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34433157/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com