簡體   English   中英

使用 JNDI 使用 Spring Boot 配置多個數據源

[英]Configuring multiple data sources with Spring Boot using JNDI

我目前正在使用 Spring Boot 構建一個 Web 應用程序,直到現在我只有一個數據源。 現在我想使用 JNDI 添加第二個。 為此,我為每個應該使用 JNDI 獲取屬性的數據源創建了一個配置類。 不幸的是,我不斷收到錯誤消息,告訴我無法創建報告實體管理器。 在嵌入第二個數據源之前,一切正常。

我嘗試了使用 Springboot + NoUniqueBeanDefinitionException 通過 jndi 查找配置兩個數據源中建議的解決方案:沒有定義 [javax.persistence.EntityManagerFactory] ​​類型的合格 bean:預期的單個匹配 bean並嘗試了幾個教程,但它不起作用。

我已經嘗試解決這個問題兩天了,但我已經沒有其他可以嘗試的想法了。 如果有人有想法或至少可以幫助我理解出了什么問題,那就太好了,謝謝!

第一個數據源的配置類

@EnableConfigurationProperties
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = {"com.project.support.database.research.repositories"},
        entityManagerFactoryRef = "researchEntityManagerFactory",
        transactionManagerRef = "researchTransactionManager")
@PropertySource("classpath:application.properties")
public class ResearchDbConfig {

    @Primary
    @Bean(name = researchDataSourceProperties")
    @ConfigurationProperties("research.spring")
    public DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Primary
    @Bean(name = "researchEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("researchDataSource") DataSource researchDataSource) {
        return builder.dataSource(researchDataSource)
                .packages("com.project.support.database.research.entities")
                .persistenceUnit("research")
                .build();
    }

    @Primary
    @Bean(name = "researchTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("researchEntityManagerFactory") EntityManagerFactory researchEntityManagerFactory) {
        return new JpaTransactionManager(researchEntityManagerFactory);
    }

}

第二個數據源的配置類

@Configuration
@EnableConfigurationProperties
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "reportingEntityManagerFactory",
        transactionManagerRef = "reportingTransactionManager",
        basePackages = {"com.project.support.database.reporting.repositories"})
@PropertySource("classpath:application.properties")

public class ReportingDbConfig {

    @Bean
    public DataSource secondaryDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        return dataSourceLookup.getDataSource(jndiSecondary().getJndiName());
    }

    @Bean(name = "reportingEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("reportingDataSource") DataSource reportingDataSource) {
        return builder.dataSource(reportingDataSource)
                .packages("com.project.support.database.reporting.entities")
                .persistenceUnit("reporting")
                .build();
    }

    @Bean(name = "reportingTransactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("reportingEntityManagerFactory") EntityManagerFactory reportingEntityManagerFactory) {
        return new JpaTransactionManager(reportingEntityManagerFactory);
    }
}

應用程序屬性

research.spring.datasource.jndi-name=jdbc/research
reporting.spring.datasource.jndi-name=jdbc/reporting

錯誤信息

26-Aug-2020 08:05:23.580 SEVERE [RMI TCP Connection(16)-192.168.178.46] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method [manageApp]
 java.lang.IllegalStateException: Error starting child
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:716)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1729)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/support]]
    at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713)
    ... 41 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reportingEntityManager' defined in class path resource [com/project/support/configuration/PersistenceReportingEntityAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1630)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1082)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
    at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:131)
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5139)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    ... 42 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:271)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:233)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:242)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:861)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:888)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1688)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1626)
    ... 61 more
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100)
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:259)
    ... 78 more

26-Aug-2020 08:05:23.581 SEVERE [RMI TCP Connection(16)-192.168.178.46] org.apache.tomcat.util.modeler.BaseModelMBean.invoke Exception invoking method [createStandardContext]
 javax.management.RuntimeOperationsException: Exception invoking method [manageApp]
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:298)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:457)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:406)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Error starting child
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:716)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1729)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:289)
    ... 33 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/support]]
    at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:441)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:198)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713)
    ... 41 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reportingEntityManager' defined in class path resource [com/project/support/configuration/PersistenceReportingEntityAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1630)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1082)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
    at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:131)
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5139)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    ... 42 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:271)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:233)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:242)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:210)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:861)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:888)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1688)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1626)
    ... 61 more
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100)
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:259)
    ... 78 more

我正在創建這個答案作為我自己的發現的占位符,該發現與此處所述的大致相同的問題有關。 我選擇了關於此的最新問題,因為現在事情可能已經改變並且表現不同。 知道 OP 如何最終解決他們的問題會很有趣。

我自己的設置是 Spring Boot 2.4.12,我的項目編譯為 WAR 工件並部署到外部 Tomcat,HikariCP 和 Oracle 庫已經在其類路徑中,Oracle 連接在 Tomcat 的 server.xml 中定義為全局資源。

[rant] 我發現調查問題的真正原因是出了名的困難,這是另一種情況,當我對 Spring Boot 感到非常沮喪時,它具有所有有用的自動配置,但沒有簡單的方法來了解引擎蓋下發生了什么以及發生了什么失火。 經過一番思考,我不怪 Spring Boot,而是我們需要面對的問題的復雜性 - 以及現代技術讓事情變得更容易的承諾 - 我一次又一次地得出結論,更深入地了解技術的內部運作仍然是必需的(有時我會以一種可怕的方式自娛自樂,思考 stackoverflow 不復存在的可能未來——那我們該怎么辦?)[咆哮結束]

因此,對於手頭的問題,來自 OP 堆棧跟蹤的最終內部異常

Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set

指出一個事實,很可能根本沒有正確讀取配置。 在我的例子中,這條消息也出現了,但是當我已經找到了一個可行的解決方案時 - 所以我沒有徹底調查它。 據我了解,Spring Boot 很可能會嘗試使用默認值初始化未在其選擇的配置中顯式設置的其余數據源屬性,並且這些值不匹配。 就我而言,application.properties 中唯一的數據源和 JNDI 相關的東西是

spring.datasource.jndi-name = java:/comp/env/jdbc/MyOracleHikariDS

在我的特定場景中,有一個隱藏在我使用的二級庫深處的第二個數據源,它指向用作緩存的嵌入式 H2 實例。 所以在類路徑中有對 H2 庫的引用,Spring Boot 似乎以某種方式將其作為默認數據源。 所以我不得不強制(通過顯式@Primary聲明)主數據源指向我真正的主數據源,它需要通過 JNDI 定義。

我想我發現(在多個 M. Deinum 評論和對其他問題的回答的幫助下)不需要還提供 TransactionManager 和 EntityManagerFactoryBean 的實現,當我只想將特定數據源定義為 @Primary - 在我的問題是數據源是如何創建的,一旦我自己創建,手動完成。 根據我的經驗,當我使用以下代碼返回數據源時,出了點問題:

@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource() {
   return DataSourceBuilder.create().build();
}

起初我以為當 Spring 嘗試將數據源初始化為上下文初始化的一部分時,Tomcat 還沒有初始化它自己的 JNDI 資源 - 所以我嘗試使用@Lazy和代理等等,但是這個最終情況並非如此。 我的私人結論(尚未證實這一點)是@ConfigurationProperties從字面上獲取屬性並覆蓋我們從 JNDI 查找中獲得的屬性。 我唯一開始工作的是以下內容。 請注意,這是一個示例,在我的工作項目中,我不必使用@EnableJpaRepositories作為我需要的第二個數據源沒有使用特定於 Spring 的存儲庫對象。

@Configuration
@EnableJpaRepositories(basePackages = "com.myproject.repositories.primary",
        entityManagerFactoryRef = "primaryEMF",
        transactionManagerRef = "primaryTM")
public class JpaPrimaryConfig {
   
   @Value("${spring.datasource.jndi-name}")
   String jndiName;

   @Bean(destroyMethod = "")
   @Primary
   public DataSource dataSource() {
      JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
      DataSource ds = dataSourceLookup.getDataSource(jndiName);
      return ds;
   }

   // we have to bind different entities to different data sources - we can do this via entity managers
   @Primary
   @Bean(name = "primaryEMF")
   public LocalContainerEntityManagerFactoryBean primaryEMF(EntityManagerFactoryBuilder builder) {
      return builder.dataSource(dataSource()).packages(DummyEntity.class).build();
   }

   @Primary
   @Bean(name = "primaryTM")
   public PlatformTransactionManager primaryTM(final @Qualifier("primaryEMF") LocalContainerEntityManagerFactoryBean emf) {
      return new JpaTransactionManager(emf.getObject());
   }

}

除了提高 HikariCP 日志級別 (logging.level.com.zaxxer=DEBUG) 之外,要檢查的另一個有用的事情是確保您的 servlet 容器確實定義了那些 JNDI 資源,這可以通過本地 Tomcat 的 jconsole 來完成。 (在沒有部署任何應用程序的情況下啟動 Tomcat 以查看它不會抱怨連接池的初始創建也很有用)

暫無
暫無

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

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