Browse Source

Polishing.

Encapsulate array support in JdbcArrayColumns.

See #1033
Original pull request: #1037.
pull/1064/head
Mark Paluch 4 years ago
parent
commit
b02ee3c083
No known key found for this signature in database
GPG Key ID: 4406B84C1661DCD1
  1. 26
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java
  2. 90
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcArrayColumns.java
  3. 12
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcPostgresDialect.java
  4. 11
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java
  5. 5
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/degraph/DependencyTests.java
  6. 11
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java

26
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultJdbcTypeFactory.java

@ -17,8 +17,8 @@ package org.springframework.data.jdbc.core.convert; @@ -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; @@ -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 { @@ -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 { @@ -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;
}
}

90
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcArrayColumns.java

@ -15,46 +15,98 @@ @@ -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();
}
}
}

12
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/dialect/JdbcPostgresDialect.java

@ -16,18 +16,20 @@ @@ -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 @@ -36,8 +38,14 @@ public class JdbcPostgresDialect extends PostgresDialect implements JdbcDialect
}
static class JdbcPostgresArrayColumns extends PostgresArrayColumns implements JdbcArrayColumns {
@Override
public Class<?> getArrayType(Class<?> userType) {
return JdbcArrayColumns.super.getArrayType(userType);
}
@Override
public String getSqlTypeRepresentation(JDBCType jdbcType) {
public String getArrayTypeName(SQLType jdbcType) {
if (jdbcType == JDBCType.DOUBLE) {
return "FLOAT8";

11
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java

@ -15,15 +15,14 @@ @@ -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; @@ -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 { @@ -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());

5
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/degraph/DependencyTests.java

@ -19,14 +19,17 @@ import static de.schauderhaft.degraph.check.JCheck.*; @@ -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

11
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java

@ -15,16 +15,15 @@ @@ -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; @@ -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 { @@ -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());
}

Loading…
Cancel
Save