Spring Boot JPA - 当“hibernate.dialect”在 JAVA 8u291 中不起作用时,对 DialectResolutionInfo 的访问不能为空

Posted

技术标签:

【中文标题】Spring Boot JPA - 当“hibernate.dialect”在 JAVA 8u291 中不起作用时,对 DialectResolutionInfo 的访问不能为空【英文标题】:Spring Boot JPA - Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not working in JAVA 8u291 【发布时间】:2021-07-16 10:34:30 【问题描述】:

我在我的本地笔记本电脑上运行它,它似乎工作正常,但每次我尝试在不同的服务器上运行时,都会出现以下错误。 (均使用 Java 8u291)

org.springframework.beans.factory.BeanCreationException:在类路径资源 [com/reclassification/HibernateConfiguration.class] 中定义名称为“jpaEntityManagerFactory”的 bean 创建错误:调用 init 方法失败;嵌套异常是 org.hibernate.service.spi.ServiceException:无法创建请求的服务 [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) 在 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) 在 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) 在 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:316) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) 在 com.reclassification.ReclassificationApplication.main(ReclassificationApplication.java:12) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源) 在 java.lang.reflect.Method.invoke(未知来源) 在 org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) 在 org.springframework.boot.loader.Launcher.launch(Launcher.java:87) 在 org.springframework.boot.loader.Launcher.launch(Launcher.java:50) 在 org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) 原因:org.hibernate.service.spi.ServiceException:无法创建请求的服务 [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) 在 org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) 在 org.hibernate.boot.internal.InFlightMetadataCollectorImpl.(InFlightMetadataCollectorImpl.java:179) 在 org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935) 在 org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) 在 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) 在 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) 在 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) 在 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758) ...省略了24个常用框架 原因:org.hibernate.HibernateException:当未设置“hibernate.dialect”时,对 DialectResolutionInfo 的访问不能为空 在 org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:100) 在 org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:54) 在 org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:137) 在 org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) 在 org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94) 在 org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)

【问题讨论】:

如何配置数据源,使用什么数据库? 【参考方案1】:

您是否缺少不同服务器上的 application.properties? 来自跟踪:

Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set at 

同时检查:answer about no dialect 可能是其他服务器连接不上DB。

【讨论】:

【参考方案2】:

“对 DialectResolutionInfo 的访问不能为空”错误似乎很笼统。在我的情况下,原因是试图在同一个 Spring Boot API 中连接到多个数据库。

就我而言,要解决它,对于 Spring Boot 2.5.4,example from Baeldung 很有帮助,this from Medium 也很有帮助。

这是为 mysql db 指定方言的 application.yml 文件:

spring:
  datasource:
    primaryDB:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:<port>/<primary db name>?charSet=LATIN1
      username: <username>
      password: <password>
      initialization-mode: always
    otherDB:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:<port>/<other db name>?charSet=LATIN1
      username: <username>
      password: <password>
      initialization-mode: always
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
  properties:
    hibernate:
      dialect: org.hibernate.dialect.MySQL5InnoDBDialect

使用主数据库的@Configuration 类:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactory",
        basePackages =  "com.foo.bar.repository" 
)
public class PrimaryDBConfig 

    @Value("$spring.datasource.primaryDB.driverClassName")
    private String driver;

    @Value("$spring.datasource.primaryDB.url")
    private String url;

    @Value("$spring.datasource.primaryDB.username")
    private String username;

    @Value("$spring.datasource.primaryDB.password")
    private String password;

    @Primary // this seemingly redundant datasource is apparently used behind
        // ... the scenes and throws an 'unsatisfied dependency' if removed.
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primaryDB")
    public DataSource dataSource() 
        return DataSourceBuilder.create().build();
    

    @Bean
    public DataSource dataSourcePrimary()
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(driver);
        config.setJdbcUrl(url);
        config.setUsername(username);
        config.setPassword(password);
        config.setAutoCommit(true);
        return new HikariDataSource(config);
    

    @Primary
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean
    entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("dataSource") DataSource dataSource) 
        return builder
                .dataSource(dataSourcePrimary())
                .packages("com.foo.bar.model")
                .persistenceUnit("primaryDB")
                .build();
    

    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("entityManagerFactory") EntityManagerFactory
                    entityManagerFactory) 
        return new JpaTransactionManager(entityManagerFactory);
    

还有“其他数据库”:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "otherDBEntityManagerFactory",
        transactionManagerRef = "otherDBTransactionManager",
        basePackages =  "com.foo.bar.otherDB" 
)
public class OtherDBConfig 

    @Value("$spring.datasource.otherDB.driverClassName")
    private String driver;

    @Value("$spring.datasource.otherDB.url")
    private String url;

    @Value("$spring.datasource.otherDB.username")
    private String username;

    @Value("$spring.datasource.otherDB.password")
    private String password;

    @Bean(name = "otherDBDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.otherDB")
    public DataSource dataSource() 
        return DataSourceBuilder.create().build();
    

    @Bean
    public DataSource dataSourceOtherDB()
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(driver);
        config.setJdbcUrl(url);
        config.setUsername(username);
        config.setPassword(password);
        config.setAutoCommit(true);
        return new HikariDataSource(config);
    

    @Bean(name = "otherDBEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean otherDBEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("otherDBDataSource") DataSource dataSource) 
        return
                builder
                        .dataSource(dataSourceOtherDB())
                        .packages("com.foo.bar.otherDB.model")
                        .persistenceUnit("otherDB")
                        .build();
    

    @Bean(name = "otherDBTransactionManager")
    public PlatformTransactionManager otherDBTransactionManager(
            @Qualifier("otherDBEntityManagerFactory") EntityManagerFactory
                    otherDBEntityManagerFactory) 
        return new JpaTransactionManager(otherDBEntityManagerFactory);
    

包结构如下:

当然,拥有多个数据源是现代微服务 API 的反模式;所以这个解决方案基本上适用于单体(和分布式单体):-)

【讨论】:

以上是关于Spring Boot JPA - 当“hibernate.dialect”在 JAVA 8u291 中不起作用时,对 DialectResolutionInfo 的访问不能为空的主要内容,如果未能解决你的问题,请参考以下文章

当加载 spring-boot 和 spring-data-jpa 时,Hibernate 无法加载 JPA 2.1 Converter

spring boot JPA 和 数据库连接

如何修复 Spring Boot 数据 jpa UnsatisfiedDependencyException

Spring Boot informix Jpa 连接

Spring Boot JPA:在自联接关系中的 JSON 视图上递归

Java - Spring Boot - Hibernate - JPA(@ManyToOne 发布错误)