簡體   English   中英

引起:org.springframework.beans.factory.NoSuchBeanDefinitionException:沒有名為“entityManagerFactory”的bean可用

[英]Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

我想配置 Spring Boot 以使用 2 個 JNDI 數據源。 我試過這個配置:

應用程序屬性

spring.production.datasource.jndi-name=java:/global/production_gateway
spring.production.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.production.datasource.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
spring.production.datasource.jpa.show-sql = true
spring.production.datasource.jpa.hibernate.ddl-auto = update

spring.warehouse.datasource.jndi-name=java:/global/production_warehouse
spring.warehouse.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.warehouse.datasource.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
spring.warehouse.datasource.jpa.show-sql = true
spring.warehouse.datasource.jpa.hibernate.ddl-auto = update

主數據庫

    @Configuration
@EnableJpaRepositories(
        basePackages = "org.datalis.plugin.production.entity", 
        entityManagerFactoryRef = "productionEntityManagerFactory", 
        transactionManagerRef = "productionTransactionManager"
    )
@EnableTransactionManagement
public class ContextProductionDatasource {

    @Primary
    @Bean(name = "productionDataSourceProperties")
    @ConfigurationProperties(prefix="spring.production.datasource")
    public JndiPropertyHolder productionDataSourceProperties() {
        return new JndiPropertyHolder();
    }   

    @Primary
    @Bean(name = "productionDataSource")
    @ConfigurationProperties(prefix="spring.production.datasource")
    public DataSource productionDataSource() {        
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(productionDataSourceProperties().getJndiName());
        return dataSource;
    }

    @Primary
    @Bean(name = "productionEntityManager") 
    public EntityManager productionEntityManager(EntityManagerFactory emf) {
        return emf.createEntityManager();
    }

    @Primary
    @Bean(name = "productionEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean productionEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.hbm2ddl.auto", "update");
        return builder
                .dataSource(productionDataSource())
                .packages("org.datalis.plugin.production.entity")
                .persistenceUnit("production")
                .properties(properties)
                .build();
    }

    @Primary
    @Bean(name = "productionTransactionManager")    
    public PlatformTransactionManager productionTransactionManager(final EntityManagerFactory emf) {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    @Primary
    @Bean(name = "productionExceptionTranslation")
    public PersistenceExceptionTranslationPostProcessor productionExceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    private static class JndiPropertyHolder {
        private String jndiName;

        public String getJndiName() {
            return jndiName;
        }

        public void setJndiName(String jndiName) {
            this.jndiName = jndiName;
        }
    }
}

第二個數據源:

    @Configuration
@EnableJpaRepositories(
        basePackages = "org.datalis.plugin.warehouse.entity", 
        entityManagerFactoryRef = "warehouseEntityManagerFactory", 
        transactionManagerRef = "warehouseTransactionManager"
    )
@EnableTransactionManagement
public class ContextWarehouseDatasource {

    @Bean(name = "warehouseDataSourceProperties")
    @ConfigurationProperties(prefix="spring.warehouse.datasource")
    public JndiPropertyHolder warehouseDataSourceProperties() {
        return new JndiPropertyHolder();
    }

    @Bean(name = "warehouseDataSource")
    @ConfigurationProperties(prefix="spring.warehouse.datasource")
    public DataSource warehouseDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(warehouseDataSourceProperties().getJndiName());
        return dataSource;
    }

    @Bean(name = "warehouseEntityManager")  
    public EntityManager warehouseEntityManager(EntityManagerFactory emf) {
        return emf.createEntityManager();
    }

    @Bean(name = "warehouseEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean warehouseEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.hbm2ddl.auto", "update");
        return builder
                .dataSource(warehouseDataSource())
                .packages("org.datalis.plugin.warehouse.entity")
                .persistenceUnit("warehouse")
                .properties(properties)
                .build();
    }

    @Bean(name = "warehouseTransactionManager")
    public PlatformTransactionManager warehouseTransactionManager(final EntityManagerFactory emf) {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }

    @Bean(name = "warehouseExceptionTranslation")
    public PersistenceExceptionTranslationPostProcessor warehouseExceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    private static class JndiPropertyHolder {
        private String jndiName;

        public String getJndiName() {
            return jndiName;
        }

        public void setJndiName(String jndiName) {
            this.jndiName = jndiName;
        }
    }
}

當我部署代碼時,出現異常:

    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available

完整的錯誤堆棧: https : //pastebin.com/bBZPZGfu

你知道我該如何解決這個問題嗎?

當我刪除:

@Primary
    @Bean(name = "productionEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean productionEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.hbm2ddl.auto", "update");
        return builder
                .dataSource(productionDataSource())
                .packages("org.datalis.plugin.production.entity")
                .persistenceUnit("production")
                .properties(properties)
                .build();
    }

包已正確部署。 知道為什么嗎?

主要問題是有 2 個不同的實體管理器,它們訪問不同的數據庫。

所以異常的原因:Spring Data JPA 嘗試創建一組存儲庫但不知道使用哪個實體管理器工廠。 默認情況下,Spring Data JPA 只需要一個實體管理器工廠 bean,最好命名為entityManagerFactory ,但您沒有這樣的。

因此,您必須在配置上非常精確:例如,您可以將代碼組織成 2 個包: ...warehouse.*app.production.* ,然后您可以指定 Spring Data JPA 的精確配置: @EnableJpaRepositories(basePackages = "...warehouse.**", entityManagerFactoryRef = "warehouseEntityManagerFactory")和用於生產@EnableJpaRepositories(basePackages = "...production.**", entityManagerFactoryRef = "productionEntityManagerFactory")

第二步是確保沒有完成默認的數據 JPA 實例化:添加配置屬性spring.data.jpa.repositories.enabled=false將解決這個問題。

並查看配置禁用任何其他@EnableJpaRepositories@EntityScan除了上面定義的精確配置

在創建LocalContainerEntityManagerFactoryBean期間不要使用注入的EntityManagerFactoryBuilder :簡單的new LocalContainerEntityManagerFactoryBean()會更好地工作。

最后但並非最不重要的是,與一般應用程序相關:您必須考慮兩階段提交事務:您有 2 個數據源,可以在單個事務中訪問它們,但每個數據源都由不同的事務管理器管理。

將注釋@ConfigurationProperties("spring.datasource")放在您的數據源定義上,例如倉庫數據源() 和生產數據源()

哎呀! 我建議遵循每個微服務模式的數據庫,並更改您的解決方案/架構,讓一個微服務和一個生產微數據庫,一個微服務和一個倉庫微數據庫!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM