Caused by: org.springframework.beans.factory.NoUniqueBeanDefinit

举报
皮牙子抓饭 发表于 2023/11/10 09:58:35 2023/11/10
【摘要】 Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.apache.ibatis.session.SqlSessionFactory' available: expected single matching bean but f...

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.apache.ibatis.session.SqlSessionFactory' available: expected single matching bean but found 3: sqlSessionFactoryMicrotek,sqlSessionFactorySinfo,sqlSessionFactoryValue

在使用 Spring 的过程中,有时候会遇到 ​​NoUniqueBeanDefinitionException​​ 异常,这个异常意味着 Spring 容器中存在多个相同类型的 Bean,但是在需要注入的地方却无法确定要使用哪个 Bean。 这个异常的具体信息是 ​​No qualifying bean of type 'org.apache.ibatis.session.SqlSessionFactory' available: expected single matching bean but found 3: sqlSessionFactoryMicrotek,sqlSessionFactorySinfo,sqlSessionFactoryValue​​。这意味着在 Spring 容器中存在三个类型为 ​​org.apache.ibatis.session.SqlSessionFactory​​ 的 Bean,但是却找不到一个唯一匹配的 Bean。 那么,我们应该如何解决这个问题呢? 解决方案之一是使用 Spring 的 ​​@Qualifier​​ 注解来明确指定要注入的 Bean。通过在需要注入的地方加上 ​​@Qualifier​​ 注解,并指定要使用的 Bean 的名称,就可以解决这个问题了。

javaCopy code@Autowired
@Qualifier("sqlSessionFactoryMicrotek")
private SqlSessionFactory sqlSessionFactory;

上面的代码中,​​@Qualifier​​ 注解指定了要使用名称为 ​​sqlSessionFactoryMicrotek​​ 的 Bean。 另一种解决方案是在 Spring 配置文件中使用 ​​@Primary​​ 注解,显式地声明一个主要的 Bean。主要的 Bean 表示在有多个符合条件的 Bean 的情况下,优先使用该 Bean。例如:

javaCopy code@Bean
@Primary
public SqlSessionFactory sqlSessionFactoryMicrotek() {
    // 配置 SqlSessionFactory 的具体实现
    return new SqlSessionFactoryMicrotek();
}

在上面的代码中,使用了 ​​@Primary​​ 注解来指定 ​​sqlSessionFactoryMicrotek​​ 为主要的 Bean。 如果以上两种解决方案无法使用,那么就需要考虑修改 Bean 的定义或者调整 Spring 的配置。可能需要排查是否有重复的 Bean 定义,或者检查是否有额外的配置文件导致了 Bean 的重复加载等错误。 在处理 ​​NoUniqueBeanDefinitionException​​ 异常时,我们应该仔细检查 Spring 容器中的 Bean 定义,确保只有一个满足条件的 Bean,并且在需要注入的地方使用适当的注解明确指定要使用的 Bean。通过这些方法,我们可以解决这个异常,使程序正常运行起来。

假设我们有一个电商平台,其中涉及多个不同的商家,每个商家都有自己的数据库。我们使用 MyBatis 进行数据库操作,每个商家都有自己的数据源和对应的 SqlSessionFactory。 首先,在 Spring 的配置文件中定义多个数据源和对应的 SqlSessionFactory:

xmlCopy code<!-- 数据源1 -->
<bean id="dataSourceMicrotek" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 数据源1的配置 -->
</bean>
<!-- 数据源2 -->
<bean id="dataSourceSinfo" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 数据源2的配置 -->
</bean>
<!-- 数据源3 -->
<bean id="dataSourceValue" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 数据源3的配置 -->
</bean>
<!-- SqlSessionFactory1 -->
<bean id="sqlSessionFactoryMicrotek" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSourceMicrotek" />
    <!-- SqlSessionFactory1的配置 -->
</bean>
<!-- SqlSessionFactory2 -->
<bean id="sqlSessionFactorySinfo" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSourceSinfo" />
    <!-- SqlSessionFactory2的配置 -->
</bean>
<!-- SqlSessionFactory3 -->
<bean id="sqlSessionFactoryValue" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSourceValue" />
    <!-- SqlSessionFactory3的配置 -->
</bean>

然后,在需要使用 SqlSessionFactory 的地方注入对应商家的 SqlSessionFactory,并使用 ​​@Qualifier​​ 注解指定要使用的 Bean 的名称:

javaCopy code@Autowired
@Qualifier("sqlSessionFactoryMicrotek")
private SqlSessionFactory sqlSessionFactoryMicrotek;
@Autowired
@Qualifier("sqlSessionFactorySinfo")
private SqlSessionFactory sqlSessionFactorySinfo;
@Autowired
@Qualifier("sqlSessionFactoryValue")
private SqlSessionFactory sqlSessionFactoryValue;

通过上述代码,我们可以分别使用不同商家的 SqlSessionFactory 进行数据库操作。 同时,我们还可以在 Service 层中根据商家 ID 动态选择对应的 SqlSessionFactory:

javaCopy code@Service
public class ProductService {
    @Autowired
    private SqlSessionFactory sqlSessionFactory;
    public List<Product> getProductsByMerchantId(Long merchantId) {
        // 根据商家 ID 获取商家信息
        Merchant merchant = merchantService.getMerchantById(merchantId);
        // 根据商家信息动态选择对应的 SqlSessionFactory
        if ("Microtek".equals(merchant.getShortName())) {
            sqlSessionFactory = sqlSessionFactoryMicrotek;
        } else if ("Sinfo".equals(merchant.getShortName())) {
            sqlSessionFactory = sqlSessionFactorySinfo;
        } else if ("Value".equals(merchant.getShortName())) {
            sqlSessionFactory = sqlSessionFactoryValue;
        }
        // 使用动态选择的 SqlSessionFactory 进行数据库操作
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 数据库操作代码
            // ...
        }
    }
}

上述示例代码演示了在电商平台应用场景中,使用不同商家的数据源和 SqlSessionFactory 进行数据库操作。通过动态选择不同的 SqlSessionFactory,可以根据不同商家的需求进行灵活的数据库访问。

​org.apache.ibatis.session.SqlSessionFactory​​​ 接口是 MyBatis 框架中的一个重要接口,用于创建 ​​org.apache.ibatis.session.SqlSession​​ 对象。SqlSession 是与数据库之间的交互接口,它封装了执行 SQL 语句和管理事务的方法。 SqlSessionFactory 接口定义了用于创建 SqlSession 对象的方法。它是 MyBatis 框架中的一个重要组件,负责创建 SqlSession 的实例,包括提供数据库连接、管理数据库会话和事务等功能。 在 MyBatis 中,SqlSessionFactory 接口的主要作用有以下几个方面: 1. 创建 SqlSession: SqlSessionFactory 通过其 ​​openSession()​​ 方法可以创建一个新的 SqlSession 对象。

javaCopy codepublic interface SqlSessionFactory {
    SqlSession openSession();
}

2. 管理数据库连接: SqlSessionFactory 负责管理数据库的连接。在创建 SqlSession 对象时,它会分配一个新的数据库连接给 SqlSession,并在 SqlSession 关闭时回收该连接。 3. 提供数据库配置信息: SqlSessionFactory 保存了 MyBatis 的数据库配置信息,包括数据源、事务隔离级别、插件等。在创建 SqlSession 对象时,会使用这些配置信息进行初始化。 4. 缓存管理: SqlSessionFactory 负责管理 MyBatis 的一级缓存(Session 级别缓存),它会为每个 SqlSession 提供一个独立的缓存空间。 5. 线程安全: SqlSessionFactory 是线程安全的,可以在多线程环境下共享使用。 使用示例:

javaCopy codepublic class MyBatisApp {
    public static void main(String[] args) {
        // 通过 MyBatis 配置文件创建 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream("mybatis-config.xml"));
        
        // 通过 SqlSessionFactory 创建 SqlSession
        try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
            // 执行数据库操作
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
        }
    }
}

 SqlSessionFactory 接口是 MyBatis 框架中的一个关键接口,用于创建 SqlSession 对象和管理数据库连接。它是 MyBatis 框架的入口点之一,在配置文件中配置 SqlSessionFactory,并通过它创建 SqlSession 对象来执行数据库操作。了解 SqlSessionFactory 的作用和用法,对于成功使用 MyBatis 进行数据库开发是非常重要的。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。