Spring Data JDBC Firebird dialect not recognized

前端 未结 5 934
谎友^
谎友^ 2021-01-13 19:28

I\'m trying to connect to Firebird database using Spring Data JDBC and Spring Boot. I\'ve created a simple app using Spring Tools. Spring Data JDBC doesn\'t recognize the di

5条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-13 20:01

    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 from JdbcOperations, typically by inspecting Connection. You can let Spring auto-discover your Dialect by registering a class that implements org.springframework.data.jdbc.repository.config.DialectResolver$JdbcDialectProvider through META-INF/spring.factories. DialectResolver discovers dialect provider implementations from the class path using Spring’s SpringFactoriesLoader.

    To be able to use Firebird, you will need to define three things:

    1. A dialect
    2. A dialect resolver
    3. 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 getDialect(JdbcOperations operations) {
            return Optional.ofNullable(
                    operations.execute((ConnectionCallback) 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.

提交回复
热议问题