当前位置: 首页 > 知识库问答 >
问题:

Spring Boot-使用多个数据源时不初始化JpaRepository

巴洲
2023-03-14

我有一个关于Spring Boot和使用JpaRepositories的多个数据源的设置的问题。

[4编辑如下]

项目的结构看起来像这样:com/mycompany/schema/AbstractJpaConfig com/myCompany/schema/domain_A/AJpaConfigance com/myCompany/schema/domain_A/实体/AEntity com/myCompany/schema/domain_A/repository/ARepository com/myCompany/schema/domain_B/BJpaConfigance com/myCompany/schema/domain_B/实体/BEntity com/myCompany/schema/domain_B/repository/BRepository

所以我有两个域(A和B),DataSource设置是单独处理的。

抽象JPA配置类用于减少冗余,并使用自定义数据源管理器来处理数据源:

public abstract class AbstractJpaConfiguration {

    private final DataSourceManager dataSources;

    public AbstractJpaConfiguration(DataSourceManager dataSources) {
        this.dataSources = dataSources;
    }

    protected abstract String persistenceUnitName();

    protected abstract Class<?> packageEntityClass();

    protected abstract DataSource useDataSource(DataSourceManager dataSources);

    public abstract LocalContainerEntityManagerFactoryBean entityManagerFactoryBean();

    public abstract PlatformTransactionManager transactionManagerBean();

    public abstract LocalContainerEntityManagerFactoryBean getEntityManagerFactoryBean();

    protected LocalContainerEntityManagerFactoryBean buildEntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(useDataSource(dataSources));
        em.setPersistenceUnitName(persistenceUnitName() + "PU");
        em.setBeanName(persistenceUnitName() + "EntityManager");
        em.setPackagesToScan(packageEntityClass().getPackage().getName());
        em.setJpaPropertyMap(persistenceProperties());
        em.setJpaVendorAdapter(jpaVendorAdapter());
        return em;
    }

    protected Map<String, String> persistenceProperties() {
        Map<String, String> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto", "validate");
        return properties;
    }

    protected JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(false);
        adapter.setGenerateDdl(false);
        return adapter;
    }

    protected PlatformTransactionManager buildTransactionManager() {
        LocalContainerEntityManagerFactoryBean emfBean = getEntityManagerFactoryBean();
        EntityManagerFactory emf = emfBean.getObject();
        return new JpaTransactionManager(emf);
    }
}

位于域A包中的配置实现如下所示:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "com.mycompany.schema.domain_A",
        entityManagerFactoryRef = "AEntityManagerFactory",
        transactionManagerRef = "ATransactionManager")
@EntityScan(basePackages = "com.mycompany.schema.domain_A")
@DependsOn("flywayMigrationInitializer")
public class AJpaConfiguration extends AbstractJpaConfiguration {

    @Autowired
    public AJpaConfiguration(DataSourceManager dataSources) {
        super(dataSources);
    }

    @Override
    protected Class<?> packageEntityClass() {
        return getClass(); // This class is located in the entity class package
    }

    @Override
    protected String persistenceUnitName() {
        return "a";
    }

    @Override
    protected DataSource useDataSource(DataSourceManager dataSources) {
        return dataSources.domainADataSource();
    }

    @Bean("aEntityManagerFactory")
    @Override
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
        return buildEntityManagerFactory();
    }

    @Bean("aTransactionManager")
    @Override
    public PlatformTransactionManager transactionManagerBean() {
        return buildTransactionManager();
    }

    @Override
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactoryBean() {
        return entityManagerFactoryBean();
    }
}

然后,实际存储库被定义为JPA存储库:

@Repository
public interface ARepository extends JpaRepository<AEntity, Long> {
}

这似乎工作,根据应用程序日志:

2018-12-14 09:45:02.997  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2018-12-14 09:45:02.997  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2018-12-14 09:45:03.012  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 9ms. Found 1 repository interface.
2018-12-14 09:45:03.029  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2018-12-14 09:45:03.029  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2018-12-14 09:45:03.085  INFO 13867 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 56ms. Found 1 repository interface.

之后,以及成功的Flyway迁移,持久化单元开始:

2018-12-14 09:45:06.459  INFO 13867 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: aPU
    ...]
2018-12-14 09:45:06.544  INFO 13867 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate Core {5.3.7.Final}
2018-12-14 09:45:06.546  INFO 13867 --- [  restartedMain] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2018-12-14 09:45:06.746  INFO 13867 --- [  restartedMain] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2018-12-14 09:45:06.922  INFO 13867 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
2018-12-14 09:45:07.976  INFO 13867 --- [  restartedMain] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2018-12-14 09:45:08.066  INFO 13867 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'aPU'

但是,当我尝试将存储库自动连接到服务时:

@Service
public class MyService {
    private final ARepository repository;

    @Autowired
    public MyService(ARepository repository) {
        this.repository = repository;
    }

    // ...
}

这是我在日志中收到的错误消息:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MyService' defined in URL [jar:file:...]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.schema.domain_A.repository.ARepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:767) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1308) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1154) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1239) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1166) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:855) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:758) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    ... 106 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.schema.domain_A.repository.ARepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1646) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1205) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1166) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:855) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:758) ~[spring-beans-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    ... 120 common frames omitted

我希望提供的信息能帮助解决这个问题<如果没有,我很乐意提供更多信息。

感谢您抽出时间,祝您今天愉快
-Alexander

编辑

我在配置类中设置了两个断点,并获得了一些新信息:

调用创建LocalContainerEntityManagerFactoryBean的方法,但是在调用PlatformTransactionManagerbean方法之前,由于缺少bean,应用程序停止。

我忽略了需要JpaRepository子类型的服务正在实现Spring SecurityUserDetailsManager接口。看起来Spring Security系统正在尝试在创建由@EnableJpaRepository拾取的JpaRepository Beans之前实例化UserDetailsManager服务。

有什么解决办法吗?

---编辑2---

我试着@导入AJpaConfigance类,它没有改变任何东西。然而,仔细观察bean实例化日志,我发现了以下消息:

2018-12-14 11:52:08.395 DEBUG 22417 --- [  restartedMain] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'aEntityManagerFactory'
2018-12-14 11:52:08.395 DEBUG 22417 --- [  restartedMain] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'aJpaConfig'

因此,Spring Boot正在为LocalContainerEntityManagerFactoryBean提取@Bean注释,但既没有创建EntityManagerFactory实例,也没有为PlatformTransactionManager提取@Bean注释。

编辑3

我设置了@Autowoe选项必需=false,现在它正在拾取bean并实例化存储库-但仅在实例化需要它们的服务之后,因此不会注入它们。

2018-12-14 13:25:30.484 DEBUG 31932 --- [  restartedMain] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'aEntityManager'
2018-12-14 13:25:33.035 DEBUG 31932 --- [  restartedMain] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'aTransactionManager'
2018-12-14 13:25:34.852 DEBUG 31932 --- [  restartedMain] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'aRepository'

我怎样才能在做其他事情之前创造豆子呢?这似乎解决了问题。

---编辑4---

多亏了@RobertNiestroj的提示,我在@Autowired注释中添加了@Lazy,这使得它们在之后被初始化。

但现在,出现了一个不同的错误:
java。lang.IllegalArgumentException:接口com。我的公司。模式。域存储库。从类加载器中看不到位置

我还应该提到,这个应用程序是由Maven模块构建的:-模式模块(JPA配置、存储库和实体类)-核心模块(应用程序配置和属性类)-[使用核心和模式的其他模块]-主模块(Spring Boot应用程序类)

共有2个答案

曹鸿风
2023-03-14

请尝试如下自动接线并检查

@Service
public class MyService {

    @Autowired
    private ARepository repository;

    // ...
}
利稳
2023-03-14

你试过@Repository(name=“Repository”)吗?IIRC,通过不提供名称,组件将使用与类匹配的名称创建,在本例中为“aRepository”。因此,当自动连接repository变量时,没有名为“repository”的组件,这会导致没有符合条件的bean异常

 类似资料:
  • 本文向大家介绍SpringBoot使用flyway初始化数据库,包括了SpringBoot使用flyway初始化数据库的使用技巧和注意事项,需要的朋友参考一下 概述 Flyway这款数据库版本工具就算大家没有使用过但也略有耳闻了,SpringBoot对该款工具进行集成的框架可以让我们在启动SpringBoot应用时自动去找SQL版本文件进行比对执行,但在迁移或初始化时往往还是需要先手动进行下数据库

  • 我有一个Spring Boot 2应用程序,它使用两个数据源——一个Oracle和一个H2。H2数据源被设置为辅助数据源,我想在启动时为它创建架构,但它从不启动schema.sql文件。这是我的数据源配置文件: 这是我的申请表。属性文件: 对于主数据源,我可以看到它进入了DataSourceInitializeInvoker,在那里它试图加载模式,但因为没有模式,所以它只能加载所有模式。sql文件

  • 初始化数据 打开MainSetup类,在Daos语句后面插入新建根用户的代码 // 初始化默认根用户 if (dao.count(User.class) == 0) { User user = new User(); user.setName("admin"); user.setPassword

  • null 代码构建良好,但当我运行它时,它会在下面抛出错误

  • 我需要初始化具有相同形状的多个Numpy数组。想知道哪种方式是最好的: 为每个人写一行: 或者有更好的方法?

  • 问题内容: 声明多维数组并为其分配值的正确方法是什么? 这就是我所拥有的: 问题答案: 尝试将适当的行替换为: 您的代码不正确,因为子数组的长度为y,索引从0开始。因此,设置为或将失败,因为索引和超出范围。 ;是初始化矩形多维数组的正确方法。如果希望将其锯齿状(每个子数组的长度可能不同),则可以使用类似于此答案的代码。但是请注意,如果您想要一个完美的矩形多维数组,John关于必须手动创建子数组的主