无法确定 "oracle" 的方言
Couldn't determine Dialect for "oracle"
我正在使用 Spring boot(2.3.5)、Oracle19c DB 和 Hibernate(5.4)。
我尝试建立多数据源连接,但我一直收到方言错误 Couldn't determine Dialect for "oracle"
。
Error creating bean with name 'jdbcDialect' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.relational.core.dialect.Dialect]: Factory method 'jdbcDialect' threw exception; nested exception is org.springframework.data.jdbc.repository.config.DialectResolver$NoDialectException: Cannot determine a dialect for org.springframework.jdbc.core.JdbcTemplate@2ba9ed19. Please provide a Dialect.
我基本上是按照this tutorial配置多数据源
application.properties
:
spring.datasource-primary.username=oracleprimary
spring.datasource-primary.password=oracleprimary
spring.datasource-primary.url=jdbc:oracle:thin:@//localhost:1521/orcl
spring.datasource-secondary.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource-secondary.username=oraclesecondary
spring.datasource-secondary.password=oraclesecondary
spring.datasource-secondary.url=jdbc:oracle:thin:@//localhost:1521/orcl
主要配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = {"com.foo.primary.repository"})
public class PrimaryDataSourceConfiguration {
@Primary
@Bean(name = "primaryDataSourceProperties")
@ConfigurationProperties("spring.datasource-primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties("spring.datasource-primary.configuration")
public DataSource primaryDataSource(@Qualifier("primaryDataSourceProperties") DataSourceProperties primaryDataSourceProperties) {
return primaryDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder primaryEntityManagerFactoryBuilder, @Qualifier("primaryDataSource") DataSource primaryDataSource) {
Map<String, String> primaryJpaProperties = new HashMap<>();
primaryJpaProperties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return primaryEntityManagerFactoryBuilder
.dataSource(primaryDataSource)
.packages("com.foo.primary.model")
.persistenceUnit("primaryDataSource")
.properties(primaryJpaProperties)
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory primaryEntityManagerFactory) {
return new JpaTransactionManager(primaryEntityManagerFactory);
}
第二种配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager",
basePackages = {"com.foo.secondary.repository"})
public class SecondaryDataSourceConfiguration {
@Bean(name = "secondaryDataSourceProperties")
@ConfigurationProperties("spring.datasource-secondary")
public DataSourceProperties secondaryDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties("spring.datasource-secondary.configuration")
public DataSource secondaryDataSource(@Qualifier("secondaryDataSourceProperties") DataSourceProperties secondaryDataSourceProperties) {
return secondaryDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
EntityManagerFactoryBuilder secondaryEntityManagerFactoryBuilder, @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
Map<String, String> secondaryJpaProperties = new HashMap<>();
secondaryJpaProperties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return secondaryEntityManagerFactoryBuilder
.dataSource(secondaryDataSource)
.packages("com.foo.secondary.model")
.persistenceUnit("secondaryDataSource")
.properties(secondaryJpaProperties)
.build();
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory secondaryEntityManagerFactory) {
return new JpaTransactionManager(secondaryEntityManagerFactory);
}
}
我也尝试了org.hibernate.dialect.Oracle10gDialect
,并在application.properties
中设置了spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
,但没有任何改变。
如何正确配置 oracle 的方言?
Spring 数据 JDBC does not support oracle dialect。您需要定义实现 JdbcDialectProvider
.
的方言
public final class OracleDialect implements DialectResolver.JdbcDialectProvider {
private static Dialect getDialect(Connection connection) throws SQLException {
DatabaseMetaData metaData = connection.getMetaData();
String name = metaData.getDatabaseProductName().toLowerCase(Locale.ROOT);
if (name.contains("oracle")) {
return AnsiDialect.INSTANCE;
}
return null;
}
@Override
public Optional<Dialect> getDialect(JdbcOperations operations) {
return Optional.ofNullable(operations.execute((ConnectionCallback<Dialect>) OracleDialect::getDialect));
}
}
在您的 build.gradle
或 pom.xml
中添加 spring-boot-starter-data-jdbc
依赖项。
然后,as mentioned in the blog,在resources/META-INF
中创建spring.factories
文件,并粘贴以下命令:
org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=<your-package>.OracleDialect
此外,由于您使用的两个数据库是相同的 (OracleDB),因此您不需要为实体管理器设置 .properties()
。正如@SternK 提到的,您只能在 application.properties
中包含 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
。
我正在使用 Spring boot(2.3.5)、Oracle19c DB 和 Hibernate(5.4)。
我尝试建立多数据源连接,但我一直收到方言错误 Couldn't determine Dialect for "oracle"
。
Error creating bean with name 'jdbcDialect' defined in class path resource [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.relational.core.dialect.Dialect]: Factory method 'jdbcDialect' threw exception; nested exception is org.springframework.data.jdbc.repository.config.DialectResolver$NoDialectException: Cannot determine a dialect for org.springframework.jdbc.core.JdbcTemplate@2ba9ed19. Please provide a Dialect.
我基本上是按照this tutorial配置多数据源
application.properties
:
spring.datasource-primary.username=oracleprimary
spring.datasource-primary.password=oracleprimary
spring.datasource-primary.url=jdbc:oracle:thin:@//localhost:1521/orcl
spring.datasource-secondary.driver-class-name=oracle.jdbc.OracleDriver
spring.datasource-secondary.username=oraclesecondary
spring.datasource-secondary.password=oraclesecondary
spring.datasource-secondary.url=jdbc:oracle:thin:@//localhost:1521/orcl
主要配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = {"com.foo.primary.repository"})
public class PrimaryDataSourceConfiguration {
@Primary
@Bean(name = "primaryDataSourceProperties")
@ConfigurationProperties("spring.datasource-primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties("spring.datasource-primary.configuration")
public DataSource primaryDataSource(@Qualifier("primaryDataSourceProperties") DataSourceProperties primaryDataSourceProperties) {
return primaryDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder primaryEntityManagerFactoryBuilder, @Qualifier("primaryDataSource") DataSource primaryDataSource) {
Map<String, String> primaryJpaProperties = new HashMap<>();
primaryJpaProperties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return primaryEntityManagerFactoryBuilder
.dataSource(primaryDataSource)
.packages("com.foo.primary.model")
.persistenceUnit("primaryDataSource")
.properties(primaryJpaProperties)
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory primaryEntityManagerFactory) {
return new JpaTransactionManager(primaryEntityManagerFactory);
}
第二种配置:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager",
basePackages = {"com.foo.secondary.repository"})
public class SecondaryDataSourceConfiguration {
@Bean(name = "secondaryDataSourceProperties")
@ConfigurationProperties("spring.datasource-secondary")
public DataSourceProperties secondaryDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties("spring.datasource-secondary.configuration")
public DataSource secondaryDataSource(@Qualifier("secondaryDataSourceProperties") DataSourceProperties secondaryDataSourceProperties) {
return secondaryDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
EntityManagerFactoryBuilder secondaryEntityManagerFactoryBuilder, @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
Map<String, String> secondaryJpaProperties = new HashMap<>();
secondaryJpaProperties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
return secondaryEntityManagerFactoryBuilder
.dataSource(secondaryDataSource)
.packages("com.foo.secondary.model")
.persistenceUnit("secondaryDataSource")
.properties(secondaryJpaProperties)
.build();
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory secondaryEntityManagerFactory) {
return new JpaTransactionManager(secondaryEntityManagerFactory);
}
}
我也尝试了org.hibernate.dialect.Oracle10gDialect
,并在application.properties
中设置了spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
,但没有任何改变。
如何正确配置 oracle 的方言?
Spring 数据 JDBC does not support oracle dialect。您需要定义实现 JdbcDialectProvider
.
public final class OracleDialect implements DialectResolver.JdbcDialectProvider {
private static Dialect getDialect(Connection connection) throws SQLException {
DatabaseMetaData metaData = connection.getMetaData();
String name = metaData.getDatabaseProductName().toLowerCase(Locale.ROOT);
if (name.contains("oracle")) {
return AnsiDialect.INSTANCE;
}
return null;
}
@Override
public Optional<Dialect> getDialect(JdbcOperations operations) {
return Optional.ofNullable(operations.execute((ConnectionCallback<Dialect>) OracleDialect::getDialect));
}
}
在您的 build.gradle
或 pom.xml
中添加 spring-boot-starter-data-jdbc
依赖项。
然后,as mentioned in the blog,在resources/META-INF
中创建spring.factories
文件,并粘贴以下命令:
org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=<your-package>.OracleDialect
此外,由于您使用的两个数据库是相同的 (OracleDB),因此您不需要为实体管理器设置 .properties()
。正如@SternK 提到的,您只能在 application.properties
中包含 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect
。