我正在尝试运行一个通过 spring-jpa 使用休眠的 spring-boot 应用程序,但是我收到了这个错误:
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:104)
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:71)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:205)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
... 21 more
我的 pom.xml 文件是这样的:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
</dependency>
</dependencies>
我的休眠配置是(方言配置在这个类的最后一个方法中):
@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.spring.app" })
public class HibernateConfig {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.spring.app.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/teste?charSet=LATIN1");
dataSource.setUsername("klebermo");
dataSource.setPassword("123");
return dataSource;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
setProperty("hibernate.hbm2ddl.auto", "create");
setProperty("hibernate.show_sql", "false");
setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
}
};
}
}
我在这里做错了什么?
首先删除所有配置 Spring Boot 将为您启动它。
确保您的类路径中有一个 application.properties
并添加以下属性。
spring.datasource.url=jdbc:postgresql://localhost:5432/teste?charSet=LATIN1
spring.datasource.username=klebermo
spring.datasource.password=123
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=create
如果您确实需要访问 SessionFactory
并且这基本上是针对相同的数据源,那么您可以执行以下操作(这也记录在 here 尽管针对 XML,而不是 JavaConfig)。
@Configuration
public class HibernateConfig {
@Bean
public HibernateJpaSessionFactoryBean sessionFactory(EntityManagerFactory emf) {
HibernateJpaSessionFactoryBean factory = new HibernateJpaSessionFactoryBean();
factory.setEntityManagerFactory(emf);
return factory;
}
}
这样您就有了 EntityManagerFactory
和 SessionFactory
。
更新: 从 Hibernate 5 开始,SessionFactory
实际上扩展了 EntityManagerFactory
。因此,要获得一个 SessionFactory
,您可以简单地将 EntityManagerFactory
转换为它或使用 unwrap
方法来获得一个。
public class SomeHibernateRepository {
@PersistenceUnit
private EntityManagerFactory emf;
protected SessionFactory getSessionFactory() {
return emf.unwrap(SessionFactory.class);
}
}
假设您有一个带有 @EnableAutoConfiguration
的 main
方法的类,您不需要 @EnableTransactionManagement
注释,因为 Spring Boot 将为您启用。 com.spring.app
包中的基本应用程序类应该足够了。
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
这样的事情应该足以检测到您的所有类(包括实体和基于 Spring Data 的存储库)。
更新:这些注释可以在较新版本的 Spring Boot 中替换为单个 @SpringBootApplication
。
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
我还建议删除 commons-dbcp
依赖项,因为这将允许 Spring Boot 配置更快、更健壮的 HikariCP
实现。
在数据库服务器关闭的情况下启动应用程序(使用 Spring Boot)时,我遇到了类似的问题。
Hibernate 可以自动确定要使用的正确方言,但为了做到这一点,它需要与数据库的实时连接。
在 application.properties 文件中添加 spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
未创建数据库时出现此错误。手动创建数据库后,它工作正常。
我也遇到了类似的问题。但是,这是由于提供的密码无效。另外,我想说您的代码似乎是使用 spring 的旧式代码。您已经提到您正在使用 Spring Boot,这意味着大部分内容将为您自动配置。休眠方言将根据类路径上可用的数据库驱动程序以及可用于正确测试连接的有效凭据自动选择。如果连接有任何问题,您将再次面临同样的错误。 application.properties 中只需要 3 个属性
# Replace with your connection string
spring.datasource.url=jdbc:mysql://localhost:3306/pdb1
# Replace with your credentials
spring.datasource.username=root
spring.datasource.password=
我遇到了同样的问题,我的问题是我试图连接的数据库不存在。
我创建了数据库,验证了 URL/连接字符串并重新运行,一切都按预期工作。
删除多余的休眠配置
如果您使用的是 Spring Boot,则无需显式提供 JPA 和 Hibernate 配置,因为 Spring Boot 可以为您做到这一点。
添加数据库配置属性
在 application.properties
Spring Boot 配置文件中,您可以添加数据库配置属性:
spring.datasource.driverClassName = org.postgresql.Driver
spring.datasource.url = jdbc:postgresql://localhost:5432/teste
spring.datasource.username = klebermo
spring.datasource.password = 123
添加 Hibernate 特定属性
而且,在同一个 application.properties
配置文件中,您还可以设置自定义 Hibernate 属性:
# Log SQL statements
spring.jpa.show-sql = false
# Hibernate ddl auto for generating the database schema
spring.jpa.hibernate.ddl-auto = create
# Hibernate database Dialect
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
而已!
我有同样的问题。将此添加到 application.properties 解决了这个问题:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
在 jpa java config 的 spring boot 中,您需要扩展 JpaBaseConfiguration 并实现它的抽象方法。
@Configuration
public class JpaConfig extends JpaBaseConfiguration {
@Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
return vendorAdapter;
}
@Override
protected Map<String, Object> getVendorProperties() {
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
}
}
以下是导致 hibernate.dialect
未设置问题的一些原因。大多数这些异常都显示在启动日志中,最后是提到的问题。
示例:在带有 Postgres DB 的 Spring Boot 应用程序中
1.检查数据库是否实际安装并启动其服务器。
org.postgresql.util.PSQLException:连接到 localhost:5432 被拒绝。检查主机名和端口是否正确以及 postmaster 是否接受 TCP/IP 连接。
java.net.ConnectException:连接被拒绝:连接
org.hibernate.service.spi.ServiceException:无法创建请求的服务 [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
2. 检查数据库名称是否正确。
org.postgresql.util.PSQLException:致命:数据库“foo”不存在在 application.properties 文件中,spring.datasource.url = jdbc:postgresql://localhost:5432/foo 但 foo 不存在。所以我从 pgAdmin 为 postgres 创建数据库 CREATE DATABASE foo;
3. 检查主机名和服务器端口是否可以访问。
org.postgresql.util.PSQLException:连接到 localhost:5431 被拒绝。检查主机名和端口是否正确以及 postmaster 是否接受 TCP/IP 连接。
java.net.ConnectException:连接被拒绝:连接
4. 检查数据库凭据是否正确。
正如@Pankaj 提到的
org.postgresql.util.PSQLException:致命:用户“postgres”的密码验证失败 spring.datasource.username= {DB USERNAME HERE} spring.datasource.password= {DB PASSWORD HERE}
发生这种情况是因为您的代码无法连接数据库。确保您有 mysql 驱动程序和用户名,密码正确。
确保您的 application.properties
具有所有正确的信息:(我将我的数据库端口从 8889
更改为 3306
它有效)
db.url: jdbc:mysql://localhost:3306/test
事实证明,如果您使用 Spring JPA,在 application.properties
文件中没有人提到 set spring.jpa.database=mysql
。这是对我来说最简单的答案,我想分享这个问题。
在我的情况下,用户无法连接到数据库。如果日志在异常之前包含警告,则会有同样的问题:
WARN HHH000342: Could not obtain connection to query metadata : Login failed for user 'my_user'.
确保你的 pom 中有你的数据库,就像 OP 一样。那是我的问题。
我的问题是嵌入式数据库已经连接。紧密连接
当 Eclipse 无法找到 JDBC 驱动程序时,我遇到了这个问题。必须从 Eclipse 中进行 gradle 刷新才能完成这项工作。
如果您使用此行:
sessionFactory.getHibernateProperties().put("hibernate.dialect", env.getProperty("hibernate.dialect"));
确保 env.getProperty("hibernate.dialect")
不为空。
相同,但在 JBoss WildFly AS 中。
解决了我的 META-INF/persistence.xml
中的属性
<properties>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
<property name="spring.jpa.database-platform" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="spring.jpa.show-sql" value="false" />
</properties>
对于那些使用 AWS MySQL RDS 的人,当您无法连接到数据库时可能会发生这种情况。转到 MySQL RDS 的 AWS 安全组设置,然后通过刷新 MyIP 来编辑入站 IP 规则。
我遇到了这个问题,上面的操作为我解决了这个问题。
我也有这个问题。就我而言,这是因为没有为 MySQL 用户分配任何授权。向我的应用程序使用的 MySQL 用户分配授权解决了该问题:
grant select, insert, delete, update on my_db.* to 'my_user'@'%';
我遇到了同样的问题,调试后发现 Spring application.properties 的数据库服务器 IP 地址错误
spring.datasource.url=jdbc:oracle:thin:@WRONG:1521/DEV
将 spring.jpa.database-platform=org.hibernate.dialect.MariaDB53Dialect
添加到我的属性文件对我有用。
PS:我正在使用 MariaDB
我在以下三种情况下重现了此错误消息:
不存在用户名写在 application.properties 文件或 persistence.properties 文件中的数据库用户,或者在您的情况下,在 HibernateConfig 文件中
部署的数据库具有该用户,但用户的密码与上述文件之一中的密码不同
数据库具有该用户且密码匹配,但该用户不具有完成 spring-boot 应用程序执行的所有数据库任务所需的所有权限
显而易见的解决方案是使用与 spring-boot 应用程序中相同的用户名和密码创建新的数据库用户,或者更改 spring-boot 应用程序文件中的用户名和密码以匹配现有数据库用户并为该数据库用户授予足够的权限。在 MySQL 数据库的情况下,可以如下所示完成:
mysql -u root -p
>CREATE USER 'theuser'@'localhost' IDENTIFIED BY 'thepassword';
>GRANT ALL ON *.* to theuser@localhost IDENTIFIED BY 'thepassword';
>FLUSH PRIVILEGES;
显然在 Postgresql 中有类似的命令,但我没有测试在 Postgresql 的情况下是否可以在这三种情况下重现此错误消息。
我遇到了同样的问题,这是由于无法连接到数据库实例引起的。在该错误上方的日志中查找休眠错误 HHH000342,它应该让您了解数据库连接失败的位置(不正确的用户名/密码、url 等)
这发生在我身上是因为我在开始会话之前没有添加 conf.configure();
:
Configuration conf = new Configuration();
conf.configure();
确保您在 application.properties 中输入了有效的详细信息以及您的数据库服务器是否可用。例如,当您连接 MySQL 时,请检查 XAMPP 是否正常运行。
我遇到了同样的问题:我尝试连接的数据库不存在。我使用了 jpa.database=default
(我猜这意味着它会尝试连接到数据库,然后自动选择方言)。一旦我启动数据库,它就可以正常工作而没有任何更改。
由于 Mysql 8.0.11 版本恢复到 5.7 为我解决了这个问题
使用休眠代码生成后我遇到了同样的错误
https://www.mkyong.com/hibernate/how-to-generate-code-with-hibernate-tools/
然后在 /src/main/java
中创建了 hibernate.cfg.xml
,但删除后没有连接参数 - 我的问题已解决
不定期副业成功案例分享
application.propertes
?我更喜欢在 HibernateConfig 类中进行所有配置的方式。