繁体   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