Polishing.
Encapsulate array support in JdbcArrayColumns. See #1033 Original pull request: #1037.
This commit is contained in:
@@ -17,8 +17,8 @@ package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.JDBCType;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns;
|
||||
import org.springframework.data.jdbc.support.JdbcUtil;
|
||||
import org.springframework.jdbc.core.ConnectionCallback;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
@@ -29,12 +29,13 @@ import org.springframework.util.Assert;
|
||||
* {@link JdbcOperations#execute(ConnectionCallback)}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class DefaultJdbcTypeFactory implements JdbcTypeFactory {
|
||||
|
||||
private final JdbcOperations operations;
|
||||
private final Function<JDBCType, String> jdbcTypeToSqlName;
|
||||
private final JdbcArrayColumns arrayColumns;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultJdbcTypeFactory}.
|
||||
@@ -42,21 +43,22 @@ public class DefaultJdbcTypeFactory implements JdbcTypeFactory {
|
||||
* @param operations must not be {@literal null}.
|
||||
*/
|
||||
public DefaultJdbcTypeFactory(JdbcOperations operations) {
|
||||
this(operations, JDBCType::getName);
|
||||
this(operations, JdbcArrayColumns.DefaultSupport.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DefaultJdbcTypeFactory}.
|
||||
*
|
||||
* @param operations must not be {@literal null}.
|
||||
* @since 2.3
|
||||
*/
|
||||
public DefaultJdbcTypeFactory(JdbcOperations operations, Function<JDBCType, String> jdbcTypeToSqlName) {
|
||||
public DefaultJdbcTypeFactory(JdbcOperations operations, JdbcArrayColumns arrayColumns) {
|
||||
|
||||
Assert.notNull(operations, "JdbcOperations must not be null");
|
||||
Assert.notNull(jdbcTypeToSqlName, "JdbcTypeToSqlName must not be null");
|
||||
Assert.notNull(arrayColumns, "JdbcArrayColumns must not be null");
|
||||
|
||||
this.operations = operations;
|
||||
this.jdbcTypeToSqlName = jdbcTypeToSqlName;
|
||||
this.arrayColumns = arrayColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,21 +66,13 @@ public class DefaultJdbcTypeFactory implements JdbcTypeFactory {
|
||||
|
||||
Assert.notNull(value, "Value must not be null.");
|
||||
|
||||
Class<?> componentType = innermostComponentType(value);
|
||||
Class<?> componentType = arrayColumns.getArrayType(value.getClass());
|
||||
|
||||
JDBCType jdbcType = JdbcUtil.jdbcTypeFor(componentType);
|
||||
Assert.notNull(jdbcType, () -> String.format("Couldn't determine JDBCType for %s", componentType));
|
||||
String typeName = jdbcTypeToSqlName.apply(jdbcType);
|
||||
String typeName = arrayColumns.getArrayTypeName(jdbcType);
|
||||
|
||||
return operations.execute((ConnectionCallback<Array>) c -> c.createArrayOf(typeName, value));
|
||||
}
|
||||
|
||||
private static Class<?> innermostComponentType(Object convertedValue) {
|
||||
|
||||
Class<?> componentType = convertedValue.getClass();
|
||||
while (componentType.isArray()) {
|
||||
componentType = componentType.getComponentType();
|
||||
}
|
||||
return componentType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,46 +15,98 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.core.dialect;
|
||||
|
||||
import java.sql.JDBCType;
|
||||
import java.sql.SQLType;
|
||||
|
||||
import org.springframework.data.relational.core.dialect.ArrayColumns;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.relational.core.dialect.ArrayColumns} that offer JDBC specific functionality.
|
||||
*
|
||||
* {@link org.springframework.data.relational.core.dialect.ArrayColumns} that offer JDBC-specific functionality.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.3
|
||||
*/
|
||||
public interface JdbcArrayColumns extends ArrayColumns {
|
||||
|
||||
JdbcArrayColumns UNSUPPORTED = new JdbcArrayColumns() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#getArrayType(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
default Class<?> getArrayType(Class<?> userType) {
|
||||
|
||||
Class<?> componentType = userType;
|
||||
while (componentType.isArray()) {
|
||||
componentType = componentType.getComponentType();
|
||||
}
|
||||
|
||||
return componentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The appropriate SQL type as a String which should be used to represent the given {@link SQLType} in an
|
||||
* {@link java.sql.Array}. Defaults to the name of the argument.
|
||||
*
|
||||
* @param jdbcType the {@link SQLType} value representing the type that should be stored in the
|
||||
* {@link java.sql.Array}. Must not be {@literal null}.
|
||||
* @return the appropriate SQL type as a String which should be used to represent the given {@link SQLType} in an
|
||||
* {@link java.sql.Array}. Guaranteed to be not {@literal null}.
|
||||
*/
|
||||
default String getArrayTypeName(SQLType jdbcType) {
|
||||
return jdbcType.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default {@link ArrayColumns} implementation for dialects that do not support array-typed columns.
|
||||
*/
|
||||
enum Unsupported implements JdbcArrayColumns {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#isSupported()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#JdbcArrayColumns(JDBCType)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getArrayType(Class<?> userType) {
|
||||
public String getArrayTypeName(SQLType jdbcType) {
|
||||
throw new UnsupportedOperationException("Array types not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlTypeRepresentation(JDBCType jdbcType) {
|
||||
throw new UnsupportedOperationException("Array types not supported");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The appropriate SQL type as a String which should be used to represent the given {@link JDBCType} in an
|
||||
* {@link java.sql.Array}. Defaults to the name of the argument.
|
||||
*
|
||||
* @param jdbcType the {@link JDBCType} value representing the type that should be stored in the
|
||||
* {@link java.sql.Array}. Must not be {@literal null}.
|
||||
* @return the appropriate SQL type as a String which should be used to represent the given {@link JDBCType} in an
|
||||
* {@link java.sql.Array}. Guaranteed to be not {@literal null}.
|
||||
* Default {@link ArrayColumns} implementation for dialects that do not support array-typed columns.
|
||||
*/
|
||||
default String getSqlTypeRepresentation(JDBCType jdbcType) {
|
||||
return jdbcType.getName();
|
||||
enum DefaultSupport implements JdbcArrayColumns {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#isSupported()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#JdbcArrayColumns(JDBCType)
|
||||
*/
|
||||
@Override
|
||||
public String getArrayTypeName(SQLType jdbcType) {
|
||||
return jdbcType.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
package org.springframework.data.jdbc.core.dialect;
|
||||
|
||||
import java.sql.JDBCType;
|
||||
import java.sql.SQLType;
|
||||
|
||||
import org.springframework.data.relational.core.dialect.PostgresDialect;
|
||||
|
||||
/**
|
||||
* JDBC specific Postgres Dialect.
|
||||
*
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.3
|
||||
*/
|
||||
public class JdbcPostgresDialect extends PostgresDialect implements JdbcDialect {
|
||||
|
||||
public static final JdbcPostgresDialect INSTANCE = new JdbcPostgresDialect();
|
||||
|
||||
private static final JdbcPostgresArrayColumns ARRAY_COLUMNS = new JdbcPostgresArrayColumns();
|
||||
|
||||
@Override
|
||||
@@ -36,8 +38,14 @@ public class JdbcPostgresDialect extends PostgresDialect implements JdbcDialect
|
||||
}
|
||||
|
||||
static class JdbcPostgresArrayColumns extends PostgresArrayColumns implements JdbcArrayColumns {
|
||||
|
||||
@Override
|
||||
public String getSqlTypeRepresentation(JDBCType jdbcType) {
|
||||
public Class<?> getArrayType(Class<?> userType) {
|
||||
return JdbcArrayColumns.super.getArrayType(userType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArrayTypeName(SQLType jdbcType) {
|
||||
|
||||
if (jdbcType == JDBCType.DOUBLE) {
|
||||
return "FLOAT8";
|
||||
|
||||
@@ -15,15 +15,14 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.repository.config;
|
||||
|
||||
import java.sql.JDBCType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -43,6 +42,7 @@ import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
|
||||
import org.springframework.data.jdbc.core.convert.RelationResolver;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
|
||||
@@ -100,11 +100,10 @@ public class AbstractJdbcConfiguration implements ApplicationContextAware {
|
||||
public JdbcConverter jdbcConverter(JdbcMappingContext mappingContext, NamedParameterJdbcOperations operations,
|
||||
@Lazy RelationResolver relationResolver, JdbcCustomConversions conversions, Dialect dialect) {
|
||||
|
||||
Function<JDBCType, String> jdbcTypeToSqlName = dialect instanceof JdbcDialect
|
||||
? ((JdbcDialect) dialect).getArraySupport()::getSqlTypeRepresentation
|
||||
: JDBCType::getName;
|
||||
JdbcArrayColumns arrayColumns = dialect instanceof JdbcDialect ? ((JdbcDialect) dialect).getArraySupport()
|
||||
: JdbcArrayColumns.DefaultSupport.INSTANCE;
|
||||
DefaultJdbcTypeFactory jdbcTypeFactory = new DefaultJdbcTypeFactory(operations.getJdbcOperations(),
|
||||
jdbcTypeToSqlName);
|
||||
arrayColumns);
|
||||
|
||||
return new BasicJdbcConverter(mappingContext, relationResolver, conversions, jdbcTypeFactory,
|
||||
dialect.getIdentifierProcessing());
|
||||
|
||||
@@ -19,14 +19,17 @@ import static de.schauderhaft.degraph.check.JCheck.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
|
||||
import de.schauderhaft.degraph.check.JCheck;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import scala.runtime.AbstractFunction1;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test package dependencies for violations.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@Disabled("org.springframework.data.jdbc.core.dialect.** needs rework")
|
||||
public class DependencyTests {
|
||||
|
||||
@Test // DATAJDBC-114
|
||||
|
||||
@@ -15,16 +15,15 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.testing;
|
||||
|
||||
import java.sql.JDBCType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -42,6 +41,7 @@ import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
|
||||
import org.springframework.data.jdbc.core.convert.RelationResolver;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcArrayColumns;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
|
||||
@@ -139,15 +139,14 @@ public class TestConfiguration {
|
||||
CustomConversions conversions, @Qualifier("namedParameterJdbcTemplate") NamedParameterJdbcOperations template,
|
||||
Dialect dialect) {
|
||||
|
||||
Function<JDBCType, String> jdbcTypeToSqlName = dialect instanceof JdbcDialect
|
||||
? ((JdbcDialect) dialect).getArraySupport()::getSqlTypeRepresentation
|
||||
: JDBCType::getName;
|
||||
JdbcArrayColumns arrayColumns = dialect instanceof JdbcDialect ? ((JdbcDialect) dialect).getArraySupport()
|
||||
: JdbcArrayColumns.DefaultSupport.INSTANCE;
|
||||
|
||||
return new BasicJdbcConverter( //
|
||||
mappingContext, //
|
||||
relationResolver, //
|
||||
conversions, //
|
||||
new DefaultJdbcTypeFactory(template.getJdbcOperations(), jdbcTypeToSqlName), //
|
||||
new DefaultJdbcTypeFactory(template.getJdbcOperations(), arrayColumns), //
|
||||
dialect.getIdentifierProcessing());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user