无法确定“oracle”的方言

Posted

技术标签:

【中文标题】无法确定“oracle”的方言【英文标题】:Couldn't determine Dialect for "oracle" 【发布时间】:2021-03-04 00:09:17 【问题描述】:

我正在使用 Spring boot(2.3.5)、Oracle19c DB 和 Hibernate(5.4)。

我尝试建立多数据源连接,但我不断收到方言错误Couldn't determine Dialect for "oracle"

在类路径资源 [org/springframework/boot/autoconfigure/data/jdbc/JdbcRepositoriesAutoConfiguration$SpringBootJdbcConfiguration.class] 中创建名称为“jdbcDialect”的 bean 时出错:通过工厂方法实例化 bean 失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.data.relational.core.dialect.Dialect]:工厂方法“jdbcDialect”抛出异常;嵌套异常是 org.springframework.data.jdbc.repository.config.DialectResolver$NoDialectException:无法确定 org.springframework.jdbc.core.JdbcTemplate@2ba9ed19 的方言。请提供方言。

我基本上是跟着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.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect @SternK,我设置在application.properties,没有成功。 【参考方案1】:

Spring Data 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.gradlepom.xml 中添加spring-boot-starter-data-jdbc 依赖项。

然后,as mentioned in the blog,在resources/META-INF中创建spring.factories文件,并粘贴以下命令:

org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=&lt;your-package&gt;.OracleDialect

另外,由于您使用的两个数据库是相同的(OracleDB),您不需要为实体管理器设置.properties()。正如@SternK 提到的,您只能在application.properties 中包含spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle12cDialect

【讨论】:

非常感谢 Spring 博客提供的参考

以上是关于无法确定“oracle”的方言的主要内容,如果未能解决你的问题,请参考以下文章

Grails 突然抛出错误无法确定数据库名称的 Hibernate 方言

续集方言错误

win7下安装oracle10g提示无法确定主机ip地址的解决方案

Spring Boot 无法从数据源确定 jdbc url

JBoss EAP 7.2 Oracle 休眠方言

Grails + sqlite