Spring Data JDBC Firebird dialect not recognized
The Spring Data JDBC library itself does not contain a Firebird dialect out of the box, so you need to provide one yourself. How to do this is documented in Annotation-based Configuration of the Spring Data JDBC documentation:
Dialects are resolved by
JdbcDialectResolver
fromJdbcOperations
, typically by inspectingConnection
. You can let Spring auto-discover yourDialect
by registering a class that implementsorg.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider
throughMETA-INF/spring.factories
.DialectResolver
discovers dialect provider implementations from the class path using Spring’sSpringFactoriesLoader
.
To be able to use Firebird, you will need to define three things:
- A dialect
- A dialect resolver
- A config file for Spring to locate the dialect resolver
The dialect can be something like (note, this dialect assumes Firebird 3 or higher):
package spring.firebird;import org.springframework.data.relational.core.dialect.AnsiDialect;import org.springframework.data.relational.core.dialect.ArrayColumns;import org.springframework.data.relational.core.dialect.LockClause;import org.springframework.data.relational.core.sql.LockOptions;public class FirebirdDialect extends AnsiDialect { public static final FirebirdDialect INSTANCE = new FirebirdDialect(); @Override public LockClause lock() { return LOCK_CLAUSE; } @Override public ArrayColumns getArraySupport() { return ArrayColumns.Unsupported.INSTANCE; } private static final LockClause LOCK_CLAUSE = new LockClause() { @Override public String getLock(LockOptions lockOptions) { return "WITH LOCK"; } @Override public Position getClausePosition() { return Position.AFTER_ORDER_BY; } };}
A dialect resolver to return the dialect if the connection is to a Firebird database.
package spring.firebird;import org.springframework.data.jdbc.repository.config.DialectResolver;import org.springframework.data.relational.core.dialect.Dialect;import org.springframework.jdbc.core.ConnectionCallback;import org.springframework.jdbc.core.JdbcOperations;import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.SQLException;import java.util.Locale;import java.util.Optional;public class FirebirdDialectResolver implements DialectResolver.JdbcDialectProvider { @Override public Optional<Dialect> getDialect(JdbcOperations operations) { return Optional.ofNullable( operations.execute((ConnectionCallback<Dialect>) FirebirdDialectResolver::getDialect)); } private static Dialect getDialect(Connection connection) throws SQLException { DatabaseMetaData metaData = connection.getMetaData(); String name = metaData.getDatabaseProductName().toLowerCase(Locale.ROOT); if (name.contains("firebird")) { return FirebirdDialect.INSTANCE; } return null; }}
Finally, you need to define a resource in META-INF
with the name spring.factories
, this file must contain the line:
org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=spring.firebird.FirebirdDialectResolver
This allows Spring Data JDBC to discover the dialect resolver and use it.
I Solve the problem with my colleague,my solution is (remove the dependency spring-boot-stater-data-jdbc keep the dependency spring-boot-starter-jdbc)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId></dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>
Working solution for MariaDB / MySQL with Spring Boot 2.3.1.RELEASE
create directory/file if not exists: resources/META-INF/spring.factories
org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider=com.yourapp.config.MariaDbDialectResolver
create class:
package com.yourapp.config;import org.springframework.data.jdbc.repository.config.DialectResolver;import org.springframework.data.relational.core.dialect.Dialect;import org.springframework.data.relational.core.dialect.MySqlDialect;import org.springframework.jdbc.core.JdbcOperations;import java.util.Optional;public class MariaDbDialectResolver implements DialectResolver.JdbcDialectProvider { @Override public Optional<Dialect> getDialect(JdbcOperations jdbcOperations) { return Optional.of(MySqlDialect.INSTANCE); }}