Browse Source

DATAJDBC-464 - Convert parameters.

Parameters now get converted to a suitable type supported by JDBC.

In order to support this the logic of finding the "right" type got moved from `BasicRelationalPersistentProperty` to `JdbcCompatibleTypes`.

Original pull request: #186.
pull/188/head
Jens Schauder 6 years ago committed by Mark Paluch
parent
commit
5ed80dfdb6
No known key found for this signature in database
GPG Key ID: 51A00FA751B91849
  1. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java
  2. 32
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java
  3. 29
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java
  4. 23
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java
  5. 7
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-hsql.sql
  6. 7
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mariadb.sql
  7. 7
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mssql.sql
  8. 7
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mysql.sql
  9. 7
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-postgres.sql
  10. 20
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
  11. 57
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/JdbcCompatibleTypes.java

2
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java

@ -67,7 +67,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
RowMapper<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod); RowMapper<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod);
return new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, mapper); return new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, mapper, converter);
} }
private RowMapper<?> createMapper(JdbcQueryMethod queryMethod) { private RowMapper<?> createMapper(JdbcQueryMethod queryMethod) {

32
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQuery.java

@ -16,17 +16,23 @@
package org.springframework.data.jdbc.repository.support; package org.springframework.data.jdbc.repository.support;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.sql.JDBCType;
import java.util.List; import java.util.List;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcValue;
import org.springframework.data.jdbc.support.JdbcUtil;
import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.relational.core.mapping.JdbcCompatibleTypes;
import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback; import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent; import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
import org.springframework.data.relational.core.mapping.event.Identifier; import org.springframework.data.relational.core.mapping.event.Identifier;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
@ -56,6 +62,7 @@ class JdbcRepositoryQuery implements RepositoryQuery {
private final JdbcQueryMethod queryMethod; private final JdbcQueryMethod queryMethod;
private final NamedParameterJdbcOperations operations; private final NamedParameterJdbcOperations operations;
private final QueryExecutor<Object> executor; private final QueryExecutor<Object> executor;
private final JdbcConverter converter;
/** /**
* Creates a new {@link JdbcRepositoryQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext} * Creates a new {@link JdbcRepositoryQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
@ -69,7 +76,7 @@ class JdbcRepositoryQuery implements RepositoryQuery {
*/ */
JdbcRepositoryQuery(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks, JdbcRepositoryQuery(ApplicationEventPublisher publisher, @Nullable EntityCallbacks callbacks,
RelationalMappingContext context, JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations, RelationalMappingContext context, JdbcQueryMethod queryMethod, NamedParameterJdbcOperations operations,
RowMapper<?> defaultRowMapper) { RowMapper<?> defaultRowMapper, JdbcConverter converter) {
Assert.notNull(publisher, "Publisher must not be null!"); Assert.notNull(publisher, "Publisher must not be null!");
Assert.notNull(context, "Context must not be null!"); Assert.notNull(context, "Context must not be null!");
@ -93,6 +100,7 @@ class JdbcRepositoryQuery implements RepositoryQuery {
rowMapper // rowMapper //
); );
this.converter = converter;
} }
private QueryExecutor<Object> createExecutor(JdbcQueryMethod queryMethod, @Nullable ResultSetExtractor extractor, private QueryExecutor<Object> createExecutor(JdbcQueryMethod queryMethod, @Nullable ResultSetExtractor extractor,
@ -209,13 +217,31 @@ class JdbcRepositoryQuery implements RepositoryQuery {
queryMethod.getParameters().getBindableParameters().forEach(p -> { queryMethod.getParameters().getBindableParameters().forEach(p -> {
String parameterName = p.getName().orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED)); convertAndAddParameter(parameters, p, objects[p.getIndex()]);
parameters.addValue(parameterName, objects[p.getIndex()]);
}); });
return parameters; return parameters;
} }
private void convertAndAddParameter(MapSqlParameterSource parameters, Parameter p, Object value) {
String parameterName = p.getName().orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED));
Class<?> parameterType = queryMethod.getParameters().getParameter(p.getIndex()).getType();
Class conversionTargetType = JdbcCompatibleTypes.INSTANCE.columnTypeForNonEntity(parameterType);
JdbcValue jdbcValue = converter.writeJdbcValue(value, conversionTargetType,
JdbcUtil.sqlTypeFor(conversionTargetType));
JDBCType jdbcType = jdbcValue.getJdbcType();
if (jdbcType == null) {
parameters.addValue(parameterName, jdbcValue.getValue());
}else {
parameters.addValue(parameterName, jdbcValue.getValue(), jdbcType.getVendorTypeNumber());
}
}
@Nullable @Nullable
private ResultSetExtractor determineResultSetExtractor(@Nullable RowMapper<?> rowMapper) { private ResultSetExtractor determineResultSetExtractor(@Nullable RowMapper<?> rowMapper) {

29
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryIntegrationTests.java

@ -23,6 +23,9 @@ import lombok.Data;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.time.Instant;
import java.util.List;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -33,11 +36,13 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.data.jdbc.testing.TestConfiguration;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries; import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
import org.springframework.data.repository.query.Param;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
@ -258,6 +263,24 @@ public class JdbcRepositoryIntegrationTests {
assertThat(repository.findById(-1L)).isEmpty(); assertThat(repository.findById(-1L)).isEmpty();
} }
@Test // DATAJDBC-464
public void executeQueryWithParameterRequiringConversion() {
Instant now = Instant.now();
DummyEntity first = repository.save(createDummyEntity());
first.setPointInTime(now.minusSeconds(1000L));
first.setName("first");
DummyEntity second = repository.save(createDummyEntity());
second.setPointInTime(now.plusSeconds(1000L));
second.setName("second");
repository.saveAll(asList(first, second));
assertThat(repository.after(now)).containsExactly(second);
}
@Test // DATAJDBC-234 @Test // DATAJDBC-234
public void findAllByQueryName() { public void findAllByQueryName() {
@ -269,17 +292,23 @@ public class JdbcRepositoryIntegrationTests {
DummyEntity entity = new DummyEntity(); DummyEntity entity = new DummyEntity();
entity.setName("Entity Name"); entity.setName("Entity Name");
return entity; return entity;
} }
interface DummyEntityRepository extends CrudRepository<DummyEntity, Long> { interface DummyEntityRepository extends CrudRepository<DummyEntity, Long> {
List<DummyEntity> findAllByNamedQuery(); List<DummyEntity> findAllByNamedQuery();
@Query("SELECT * FROM DUMMY_ENTITY WHERE POINT_IN_TIME > :threshhold")
List<DummyEntity> after(@Param("threshhold")Instant threshhold);
} }
@Data @Data
static class DummyEntity { static class DummyEntity {
String name; String name;
@Id private Long idProp; @Id private Long idProp;
Instant pointInTime;
} }
} }

23
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryQueryUnitTests.java

@ -28,6 +28,9 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.data.jdbc.core.convert.BasicJdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.RelationResolver;
import org.springframework.data.mapping.callback.EntityCallbacks; import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback; import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
@ -58,6 +61,7 @@ public class JdbcRepositoryQueryUnitTests {
ApplicationEventPublisher publisher; ApplicationEventPublisher publisher;
EntityCallbacks callbacks; EntityCallbacks callbacks;
RelationalMappingContext context; RelationalMappingContext context;
JdbcConverter converter;
@Before @Before
public void setup() throws NoSuchMethodException { public void setup() throws NoSuchMethodException {
@ -73,6 +77,7 @@ public class JdbcRepositoryQueryUnitTests {
this.publisher = mock(ApplicationEventPublisher.class); this.publisher = mock(ApplicationEventPublisher.class);
this.callbacks = mock(EntityCallbacks.class); this.callbacks = mock(EntityCallbacks.class);
this.context = mock(RelationalMappingContext.class, RETURNS_DEEP_STUBS); this.context = mock(RelationalMappingContext.class, RETURNS_DEEP_STUBS);
this.converter = new BasicJdbcConverter(context, mock(RelationResolver.class));
} }
@Test // DATAJDBC-165 @Test // DATAJDBC-165
@ -82,7 +87,7 @@ public class JdbcRepositoryQueryUnitTests {
Assertions.assertThatExceptionOfType(IllegalStateException.class) // Assertions.assertThatExceptionOfType(IllegalStateException.class) //
.isThrownBy( .isThrownBy(
() -> new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) () -> new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {})); .execute(new Object[] {}));
} }
@ -92,7 +97,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn("some sql statement").when(queryMethod).getDeclaredQuery();
doReturn(RowMapper.class).when(queryMethod).getRowMapperClass(); doReturn(RowMapper.class).when(queryMethod).getRowMapperClass();
JdbcRepositoryQuery query = new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, JdbcRepositoryQuery query = new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations,
defaultRowMapper); defaultRowMapper, converter);
query.execute(new Object[] {}); query.execute(new Object[] {});
@ -104,7 +109,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn("some sql statement").when(queryMethod).getDeclaredQuery();
JdbcRepositoryQuery query = new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, JdbcRepositoryQuery query = new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations,
defaultRowMapper); defaultRowMapper, converter);
query.execute(new Object[] {}); query.execute(new Object[] {});
@ -117,7 +122,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn("some sql statement").when(queryMethod).getDeclaredQuery();
doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass(); doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass();
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {}); .execute(new Object[] {});
verify(operations) // verify(operations) //
@ -130,7 +135,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn("some sql statement").when(queryMethod).getDeclaredQuery(); doReturn("some sql statement").when(queryMethod).getDeclaredQuery();
doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass(); doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass();
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {}); .execute(new Object[] {});
ArgumentCaptor<CustomResultSetExtractor> captor = ArgumentCaptor.forClass(CustomResultSetExtractor.class); ArgumentCaptor<CustomResultSetExtractor> captor = ArgumentCaptor.forClass(CustomResultSetExtractor.class);
@ -149,7 +154,7 @@ public class JdbcRepositoryQueryUnitTests {
doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass(); doReturn(CustomResultSetExtractor.class).when(queryMethod).getResultSetExtractorClass();
doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass(); doReturn(CustomRowMapper.class).when(queryMethod).getRowMapperClass();
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {}); .execute(new Object[] {});
ArgumentCaptor<CustomResultSetExtractor> captor = ArgumentCaptor.forClass(CustomResultSetExtractor.class); ArgumentCaptor<CustomResultSetExtractor> captor = ArgumentCaptor.forClass(CustomResultSetExtractor.class);
@ -172,7 +177,7 @@ public class JdbcRepositoryQueryUnitTests {
when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier()) when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier())
.thenReturn("some identifier"); .thenReturn("some identifier");
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {}); .execute(new Object[] {});
verify(publisher).publishEvent(any(AfterLoadEvent.class)); verify(publisher).publishEvent(any(AfterLoadEvent.class));
@ -189,7 +194,7 @@ public class JdbcRepositoryQueryUnitTests {
when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier()) when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier())
.thenReturn("some identifier"); .thenReturn("some identifier");
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper) new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter)
.execute(new Object[] {}); .execute(new Object[] {});
verify(publisher, times(2)).publishEvent(any(AfterLoadEvent.class)); verify(publisher, times(2)).publishEvent(any(AfterLoadEvent.class));
@ -207,7 +212,7 @@ public class JdbcRepositoryQueryUnitTests {
when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier()) when(context.getRequiredPersistentEntity(DummyEntity.class).getIdentifierAccessor(any()).getIdentifier())
.thenReturn("some identifier"); .thenReturn("some identifier");
new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper).execute(new Object[] {}); new JdbcRepositoryQuery(publisher, callbacks, context, queryMethod, operations, defaultRowMapper, converter).execute(new Object[] {});
verify(publisher).publishEvent(any(AfterLoadEvent.class)); verify(publisher).publishEvent(any(AfterLoadEvent.class));
verify(callbacks).callback(AfterLoadCallback.class, dummyEntity); verify(callbacks).callback(AfterLoadCallback.class, dummyEntity);

7
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-hsql.sql

@ -1 +1,6 @@
CREATE TABLE dummy_entity ( id_Prop BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100)) CREATE TABLE dummy_entity
(
id_Prop BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP
);

7
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mariadb.sql

@ -1 +1,6 @@
CREATE TABLE dummy_entity (id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100)); CREATE TABLE dummy_entity
(
id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP(3)
);

7
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mssql.sql

@ -1,2 +1,7 @@
DROP TABLE IF EXISTS dummy_entity; DROP TABLE IF EXISTS dummy_entity;
CREATE TABLE dummy_entity (id_Prop BIGINT IDENTITY PRIMARY KEY, NAME VARCHAR(100)); CREATE TABLE dummy_entity
(
id_Prop BIGINT IDENTITY PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP
);

7
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-mysql.sql

@ -1 +1,6 @@
CREATE TABLE dummy_entity (id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100)); CREATE TABLE dummy_entity
(
id_Prop BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP(3)
);

7
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.repository/JdbcRepositoryIntegrationTests-postgres.sql

@ -1,2 +1,7 @@
DROP TABLE dummy_entity; DROP TABLE dummy_entity;
CREATE TABLE dummy_entity (id_Prop SERIAL PRIMARY KEY, NAME VARCHAR(100)); CREATE TABLE dummy_entity
(
id_Prop SERIAL PRIMARY KEY,
NAME VARCHAR(100),
POINT_IN_TIME TIMESTAMP
);

20
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java

@ -49,15 +49,6 @@ import org.springframework.util.StringUtils;
public class BasicRelationalPersistentProperty extends AnnotationBasedPersistentProperty<RelationalPersistentProperty> public class BasicRelationalPersistentProperty extends AnnotationBasedPersistentProperty<RelationalPersistentProperty>
implements RelationalPersistentProperty { implements RelationalPersistentProperty {
private static final Map<Class<?>, Class<?>> javaToDbType = new LinkedHashMap<>();
static {
javaToDbType.put(Enum.class, String.class);
javaToDbType.put(ZonedDateTime.class, String.class);
javaToDbType.put(Temporal.class, Date.class);
}
private final RelationalMappingContext context; private final RelationalMappingContext context;
private final Lazy<SqlIdentifier> columnName; private final Lazy<SqlIdentifier> columnName;
private final Lazy<Optional<SqlIdentifier>> collectionIdColumnName; private final Lazy<Optional<SqlIdentifier>> collectionIdColumnName;
@ -179,7 +170,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
return columnType; return columnType;
} }
Class componentColumnType = columnTypeForNonEntity(getActualType()); Class componentColumnType = JdbcCompatibleTypes.INSTANCE.columnTypeForNonEntity(getActualType());
while (componentColumnType.isArray()) { while (componentColumnType.isArray()) {
componentColumnType = componentColumnType.getComponentType(); componentColumnType = componentColumnType.getComponentType();
@ -286,15 +277,6 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
return idProperty.getColumnType(); return idProperty.getColumnType();
} }
private Class columnTypeForNonEntity(Class type) {
return javaToDbType.entrySet().stream() //
.filter(e -> e.getKey().isAssignableFrom(type)) //
.map(e -> (Class) e.getValue()) //
.findFirst() //
.orElseGet(() -> ClassUtils.resolvePrimitiveIfNecessary(type));
}
private Class columnTypeForReference() { private Class columnTypeForReference() {
Class<?> componentType = getTypeInformation().getRequiredComponentType().getType(); Class<?> componentType = getTypeInformation().getRequiredComponentType().getType();

57
spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/JdbcCompatibleTypes.java

@ -0,0 +1,57 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.core.mapping;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.util.ClassUtils;
/**
* Utility that determines the necessary type conversions between Java types used in the domain model and types
* compatible with JDBC drivers.
*
* @author Jens Schauder
* @since 2.0
*/
public enum JdbcCompatibleTypes {
INSTANCE {
private final Map<Class<?>, Class<?>> javaToDbType = new LinkedHashMap<>();
{
javaToDbType.put(Enum.class, String.class);
javaToDbType.put(ZonedDateTime.class, String.class);
javaToDbType.put(Temporal.class, Date.class);
}
public Class columnTypeForNonEntity(Class type) {
return javaToDbType.entrySet().stream() //
.filter(e -> e.getKey().isAssignableFrom(type)) //
.map(e -> (Class) e.getValue()) //
.findFirst() //
.orElseGet(() -> ClassUtils.resolvePrimitiveIfNecessary(type));
}
};
public abstract Class columnTypeForNonEntity(Class type);
}
Loading…
Cancel
Save