Spring 与 MyBatis:预期有一个匹配的 bean,但发现了 2 个

2023-12-29

我一直在 MyBatis 中使用 Spring,它对于单个数据库来说运行得非常好。我在尝试添加另一个数据库时遇到了困难(请参阅Github 上可重现的示例 https://github.com/alexwoolford/mybatis-spring-multiple-mysql-reproducible-example).

我正在使用 Spring Java 配置(即不是 XML)。我见过的大多数示例都展示了如何使用 XML 来实现这一点。

我有两个数据配置类(A 和 B),如下所示:

@Configuration
@MapperScan("io.woolford.database.mapper")
public class DataConfigDatabaseA {

    @Bean(name="dataSourceA")
    public DataSource dataSourceA() throws SQLException {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriver(new com.mysql.jdbc.Driver());
        dataSource.setUrl("jdbc:mysql://" + dbHostA + "/" + dbDatabaseA);
        dataSource.setUsername(dbUserA);
        dataSource.setPassword(dbPasswordA);
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSourceA());
        return sessionFactory.getObject();
    }
}

两个映射器和一个自动装配映射器的服务:

@Service
public class DbService {

    @Autowired
    private DbMapperA dbMapperA;

    @Autowired
    private DbMapperB dbMapperB;

    public List<Record> getDabaseARecords(){
        return dbMapperA.getDatabaseARecords();
    }

    public List<Record> getDabaseBRecords(){
        return dbMapperB.getDatabaseBRecords();
    }

}

应用程序不会启动:

Error creating bean with name 'dataSourceInitializer': 
  Invocation of init method failed; nested exception is 
    org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
      No qualifying bean of type [javax.sql.DataSource] is defined: 
        expected single matching bean but found 2: dataSourceB,dataSourceA

我读过可以使用@Qualifier注释来消除自动装配的歧义,尽管我不确定在哪里添加它。

你能看出我错在哪里吗?


如果你想同时使用两个数据源并且它们没有主从关系,你应该禁用DataSourceAutoConfiguration by @EnableAutoConfiguration(excludes = {DataSourceAutoConfiguration.class})在您的应用程序中注释为@SpringBootApplication。之后,您可以创建自己的SqlSessionFactory并捆绑你自己的DataSource。如果您也想使用DataSourceTransactionManager,你也应该这样做。

在这种情况下,您还没有禁用DataSourceAutoConfiguration,所以spring框架会尝试@Autowired只有一个DataSource但得到了两个,发生错误。

正如我之前所说,你应该禁用DataSourceAutoConfiguration并手动配置它。

您可以禁用数据源自动配置,如下所示:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class YourApplication implements CommandLineRunner {
    public static void main (String... args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

如果你确实想同时使用多个数据库,我建议你手动注册适当的bean,例如:

package xyz.cloorc.boot.mybatis;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
public class SimpleTest {

    private DataSource dsA;
    private DataSource dsB;

    @Bean(name = "dataSourceA")
    public DataSource getDataSourceA() {
        return dsA != null ? dsA : (dsA = new BasicDataSource());
    }

    @Bean(name = "dataSourceB")
    public DataSource getDataSourceB() {
        return dsB != null ? dsB : (dsB = new BasicDataSource());
    }

    @Bean(name = "sqlSessionFactoryA")
    public SqlSessionFactory getSqlSessionFactoryA() throws Exception {
        // set DataSource to dsA
        return new SqlSessionFactoryBean().getObject();
    }

    @Bean(name = "sqlSessionFactoryB")
    public SqlSessionFactory getSqlSessionFactoryB() throws Exception {
        // set DataSource to dsB
        return new SqlSessionFactoryBean().getObject();
    }
}

@Repository
public class SimpleDao extends SqlSessionDaoSupport {

    @Resource(name = "sqlSessionFactoryA")
    SqlSessionFactory factory;

    @PostConstruct
    public void init() {
        setSqlSessionFactory(factory);
    }

    @Override
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

    public <T> T get (Object id) {
        return super.getSqlSession().selectOne("sql statement", "sql parameters");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 与 MyBatis:预期有一个匹配的 bean,但发现了 2 个 的相关文章

随机推荐

  • asp.net core RC2图像不显示

    我想做的是显示网络根文件夹中的图像 这就是我尝试执行此操作的方式 下面的课程只是实验性的 只是我尝试的例子 目前正在读取的文件夹中只有一张图像 rootPath 也取自 hostingEnvironment WebRootPath publ
  • 在 python 中将一个 tar 中的文件添加到另一个 tar 中

    我想制作一份 tar 的副本 删除一些文件 基于它们的名称以及可能的其他属性 如符号链接等 因为我已经在 python 中打开了 tar 文件 所以我想在 python 中执行此操作 我知道 TarFile getmembers 返回 Ta
  • 在项目中包含 Paragonie Halite 找不到变量和函数

    我已经在 Windows 上为 PHP 7 安装了 libsodium 并且正在使用 PHPStorm 开发我的项目 我还安装了 Paragonie 的 Halite 如果 libsodium 扩展安装不正确 它甚至无法安装 IDE 还会找
  • 使连续的数字列名称带有字母前缀

    我想向我的数据集添加标签 然而 问题是我的数据集中有太多列 因此手动添加标签很费力 我有 33 列 包括label列在末尾 如下所示 features lt c f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
  • vue-chartjs:您可能需要适当的加载器来处理此文件类型,当前没有配置加载器来处理此文件

    我按照说明添加了 vue chartjs https vue chartjs org ja guide https vue chartjs org ja guide 纱线添加 vue chartjs 电子邮件受保护 cdn cgi l em
  • 有人可以转换代码,以便它使用 EXEC @sql 而不是 EXEC sp_executesql 吗?

    这是我想要转换的存储过程 ALTER PROCEDURE GetName ClientName nVarchar max AS BEGIN DECLARE sql NVARCHAR MAX DECLARE name NVARCHAR MAX
  • PHP 自动生存

    更新 我提出这个问题的初衷是确定 PHP 是否确实具有此功能 这在答案对标量问题的关注中被忽略了 请参阅这个新问题 PHP 有自动生存功能吗 https stackoverflow com questions 5964420 does ph
  • 使用反射的 F# 通用 Map.count

    这是对此的后续上一个问题 https stackoverflow com questions 55877793 f pattern matching on a generic type map 55878543 55878543 但有不同的
  • Openstack.Net SDK无法访问带区域的服务

    使用我们自己的硬件 我们安装了带有所有组件的普通 openstack 但是由于区域问题 我在访问除身份之外的服务时遇到问题 使用的代码如下 使用我们创建的管理员帐户和管理员租户进行调用 public static void TestAcce
  • 从组件分派操作时未调用 ngrx 效果

    我遇到了 ngrx 存储问题 没有发送一个动作来处理它 这是尝试分派的组件 signin this formStatus submitted true if this formStatus form valid this store dis
  • 将 Android 模拟器快照移动到另一台计算机

    因此 我需要制作一个可供多人 跨多台计算机使用的快照 我正在做一些测试 需要设置很多东西来测试一件事 设置需要一些时间 我希望能够只创建一个 avd 并让几个人使用它 我以为我可以通过制作一个然后拍一张快照来做到这一点 但无论我做什么 我就
  • 在 EPPlus 中设置*两者*值和公式

    有什么办法可以设置吗both the Value Formula单元格的属性以便它们保留到写入的 XLSX 文件中 由于EPPlus不计算公式 它依赖excel来计算 所以我为用户预先计算结果 这样 如果他们不打开文件 而是重新上传文件 则
  • 服务器事件中的最终消息直到心跳才被推送

    我们在通过服务堆栈发送的最终消息等待下一个心跳发送时遇到问题 我们认为它类似于 Servicestack 服务器发送事件 https stackoverflow com questions 25960723 servicestack ser
  • 在 LIBGDX 中绘制弯曲的自定义对象?

    我最近一直在研究LibGDX 似乎碰壁了 如图所示 蓝点代表用户的手指 它本身的地图生成是我似乎陷入困境的地方 LibGDX是否提供了动态绘制的方法弯曲的物体 我可以简单地自己将它们生成为图像 但是图像会被极大地拉伸到手指可以容纳 3 个手
  • 检查异步方法的 Received() 调用

    当我运行以下代码时 Test public async Task Can Test Update var response await controller UpdateAsync Guid NewGuid response Valid S
  • 实体框架生成short而不是int

    我们对 Oracle 数据库使用实体框架数据库优先 因为某些原因Number 5 变成Int16 short Max Number 5 值为99999 Max Int16值为32767 问题 有没有办法指示映射器进行翻译Number 5 t
  • mlr3 - 基准测试:状态消息仅在完整基准测试完成后显示

    我想监控 mlr3 中 benchmark 的进度 对多个模型进行基准测试 包括对大型数据集进行超参数调整 可能需要数小时甚至数天的时间 我希望能够在基准测试运行时监视进度 以便我可以决定是否中止基准测试 此外 如果在此过程中打印状态消息
  • 在 Chrome DevTools 的源中移动“调试器”面板?

    当我使用宽屏时 我总是让 DevTools 在浏览器中垂直显示 我无法再让调试器面板显示在源文件内容下方 为了澄清我指的是哪个面板 它位于 源 选项卡下 然后是右侧的 调试器 面板 您可以在其中看到监视 调用堆栈 范围 断点等 您知道 所有
  • 使用带参数的命令模式

    我有一个像这样的可重装武器类 public class ReloadableWeapon private int numberofbullets public ReloadableWeapon int numberofbullets thi
  • Spring 与 MyBatis:预期有一个匹配的 bean,但发现了 2 个

    我一直在 MyBatis 中使用 Spring 它对于单个数据库来说运行得非常好 我在尝试添加另一个数据库时遇到了困难 请参阅Github 上可重现的示例 https github com alexwoolford mybatis spri