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 UnsatisfiedDependencyException