Update @Query argument conversion to handle Collection<Enum>.

+ Copy logic from QueryMapper#convertToJdbcValue to resolve Iterable
  arguments on findBy* query methods to resolve the same for @Query.
+ Use parameter ResolvableType instead of Class to retain generics info.

Original pull request #1226
Closes #1212
This commit is contained in:
Chirag Tailor
2022-04-07 08:32:45 -05:00
committed by Jens Schauder
parent ad058a029f
commit 4fb0ccf721
22 changed files with 347 additions and 36 deletions

View File

@@ -287,8 +287,7 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
return writeJdbcValue(value, columnType, JdbcUtil.jdbcTypeFor(sqlType));
}
/*
/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.convert.JdbcConverter#writeValue(java.lang.Object, java.lang.Class, int)
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 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.
@@ -19,9 +19,12 @@ import static org.springframework.data.jdbc.repository.query.JdbcQueryExecution.
import java.lang.reflect.Constructor;
import java.sql.SQLType;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
@@ -29,6 +32,7 @@ import org.springframework.data.jdbc.core.mapping.JdbcValue;
import org.springframework.data.jdbc.support.JdbcUtil;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
import org.springframework.data.relational.repository.query.RelationalParameters;
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
@@ -53,6 +57,7 @@ import org.springframework.util.StringUtils;
* @author Maciej Walkowiak
* @author Mark Paluch
* @author Hebert Coelho
* @author Chirag Tailor
* @since 2.0
*/
public class StringBasedJdbcQuery extends AbstractJdbcQuery {
@@ -157,11 +162,34 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
String parameterName = p.getName().orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED));
Class<?> parameterType = queryMethod.getParameters().getParameter(p.getIndex()).getType();
Class<?> conversionTargetType = JdbcColumnTypes.INSTANCE.resolvePrimitiveType(parameterType);
RelationalParameters.RelationalParameter parameter = queryMethod.getParameters().getParameter(p.getIndex());
ResolvableType resolvableType = parameter.getResolvableType();
Class<?> type = resolvableType.resolve();
Assert.notNull(type, "@Query parameter could not be resolved!");
JdbcValue jdbcValue = converter.writeJdbcValue(value, conversionTargetType,
JdbcUtil.targetSqlTypeFor(conversionTargetType));
JdbcValue jdbcValue;
if (value instanceof Iterable) {
List<Object> mapped = new ArrayList<>();
SQLType jdbcType = null;
Class<?> elementType = resolvableType.getGeneric(0).resolve();
Assert.notNull(elementType, "@Query Iterable parameter generic type could not be resolved!");
for (Object o : (Iterable<?>) value) {
JdbcValue elementJdbcValue = converter.writeJdbcValue(o, elementType,
JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(elementType)));
if (jdbcType == null) {
jdbcType = elementJdbcValue.getJdbcType();
}
mapped.add(elementJdbcValue.getValue());
}
jdbcValue = JdbcValue.of(mapped, jdbcType);
} else {
jdbcValue = converter.writeJdbcValue(value, type,
JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(type)));
}
SQLType jdbcType = jdbcValue.getJdbcType();
if (jdbcType == null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 the original author or authors.
* Copyright 2019-2022 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.
@@ -16,6 +16,7 @@
package org.springframework.data.jdbc.repository;
import static java.util.Arrays.*;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.SoftAssertions.*;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.*;
@@ -23,6 +24,7 @@ import static org.springframework.test.context.TestExecutionListeners.MergeMode.
import java.math.BigDecimal;
import java.sql.JDBCType;
import java.util.Date;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -36,6 +38,7 @@ import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
import org.springframework.data.jdbc.testing.AssumeFeatureTestExecutionListener;
import org.springframework.data.jdbc.testing.TestConfiguration;
@@ -50,6 +53,7 @@ import org.springframework.transaction.annotation.Transactional;
*
* @author Jens Schauder
* @author Sanghyuk Jung
* @author Chirag Tailor
*/
@ContextConfiguration
@Transactional
@@ -69,18 +73,19 @@ public class JdbcRepositoryCustomConversionIntegrationTests {
}
@Bean
EntityWithBooleanRepository repository() {
return factory.getRepository(EntityWithBooleanRepository.class);
EntityWithStringyBigDecimalRepository repository() {
return factory.getRepository(EntityWithStringyBigDecimalRepository.class);
}
@Bean
JdbcCustomConversions jdbcCustomConversions() {
return new JdbcCustomConversions(asList(StringToBigDecimalConverter.INSTANCE, BigDecimalToString.INSTANCE,
CustomIdReadingConverter.INSTANCE, CustomIdWritingConverter.INSTANCE));
CustomIdReadingConverter.INSTANCE, CustomIdWritingConverter.INSTANCE, DirectionToIntegerConverter.INSTANCE,
NumberToDirectionConverter.INSTANCE, IntegerToDirectionConverter.INSTANCE));
}
}
@Autowired EntityWithBooleanRepository repository;
@Autowired EntityWithStringyBigDecimalRepository repository;
/**
* In PostrgreSQL this fails if a simple converter like the following is used.
@@ -143,13 +148,50 @@ public class JdbcRepositoryCustomConversionIntegrationTests {
});
}
interface EntityWithBooleanRepository extends CrudRepository<EntityWithStringyBigDecimal, CustomId> {}
@Test // GH-1212
void queryByEnumTypeIn() {
EntityWithStringyBigDecimal entityA = new EntityWithStringyBigDecimal();
entityA.direction = Direction.LEFT;
EntityWithStringyBigDecimal entityB = new EntityWithStringyBigDecimal();
entityB.direction = Direction.CENTER;
EntityWithStringyBigDecimal entityC = new EntityWithStringyBigDecimal();
entityC.direction = Direction.RIGHT;
repository.saveAll(asList(entityA, entityB, entityC));
assertThat(repository.findByEnumTypeIn(asList(Direction.LEFT, Direction.RIGHT)))
.extracting(entity -> entity.direction).containsExactlyInAnyOrder(Direction.LEFT, Direction.RIGHT);
}
@Test // GH-1212
void queryByEnumTypeEqual() {
EntityWithStringyBigDecimal entityA = new EntityWithStringyBigDecimal();
entityA.direction = Direction.LEFT;
EntityWithStringyBigDecimal entityB = new EntityWithStringyBigDecimal();
entityB.direction = Direction.CENTER;
EntityWithStringyBigDecimal entityC = new EntityWithStringyBigDecimal();
entityC.direction = Direction.RIGHT;
repository.saveAll(asList(entityA, entityB, entityC));
assertThat(repository.findByEnumTypeIn(singletonList(Direction.CENTER))).extracting(entity -> entity.direction)
.containsExactly(Direction.CENTER);
}
interface EntityWithStringyBigDecimalRepository extends CrudRepository<EntityWithStringyBigDecimal, CustomId> {
@Query("SELECT * FROM ENTITY_WITH_STRINGY_BIG_DECIMAL WHERE DIRECTION IN (:types)")
List<EntityWithStringyBigDecimal> findByEnumTypeIn(List<Direction> types);
@Query("SELECT * FROM ENTITY_WITH_STRINGY_BIG_DECIMAL WHERE DIRECTION = :type")
List<EntityWithStringyBigDecimal> findByEnumType(Direction type);
}
private static class EntityWithStringyBigDecimal {
@Id CustomId id;
String stringyNumber;
String stringyNumber = "1.0";
OtherEntity reference;
Direction direction = Direction.CENTER;
}
private static class CustomId {
@@ -167,6 +209,10 @@ public class JdbcRepositoryCustomConversionIntegrationTests {
Date created;
}
enum Direction {
LEFT, CENTER, RIGHT
}
@WritingConverter
enum StringToBigDecimalConverter implements Converter<String, JdbcValue> {
@@ -214,4 +260,64 @@ public class JdbcRepositoryCustomConversionIntegrationTests {
}
}
@WritingConverter
enum DirectionToIntegerConverter implements Converter<Direction, JdbcValue> {
INSTANCE;
@Override
public JdbcValue convert(Direction source) {
int integer;
switch (source) {
case LEFT:
integer = -1;
break;
case CENTER:
integer = 0;
break;
case RIGHT:
integer = 1;
break;
default:
throw new IllegalArgumentException();
}
return JdbcValue.of(integer, JDBCType.INTEGER);
}
}
@ReadingConverter // Needed for Oracle since the JDBC driver returns BigDecimal on read
enum NumberToDirectionConverter implements Converter<Number, Direction> {
INSTANCE;
@Override
public Direction convert(Number source) {
int sourceAsInt = source.intValue();
if (sourceAsInt == 0) {
return Direction.CENTER;
} else if (sourceAsInt < 0) {
return Direction.LEFT;
} else {
return Direction.RIGHT;
}
}
}
@ReadingConverter
enum IntegerToDirectionConverter implements Converter<Integer, Direction> {
INSTANCE;
@Override
public Direction convert(Integer source) {
if (source == 0) {
return Direction.CENTER;
} else if (source < 0) {
return Direction.LEFT;
} else {
return Direction.RIGHT;
}
}
}
}

View File

@@ -20,10 +20,6 @@ import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.SoftAssertions.*;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Value;
import java.io.IOException;
import java.sql.ResultSet;
import java.time.Instant;
@@ -33,6 +29,7 @@ import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -75,11 +72,16 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.jdbc.JdbcTestUtils;
import org.springframework.transaction.annotation.Transactional;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Value;
/**
* Very simple use cases for creation and usage of JdbcRepositories.
*
* @author Jens Schauder
* @author Mark Paluch
* @author Chirag Tailor
*/
@Transactional
@TestExecutionListeners(value = AssumeFeatureTestExecutionListener.class, mergeMode = MERGE_WITH_DEFAULTS)
@@ -575,6 +577,38 @@ public class JdbcRepositoryIntegrationTests {
assertThat(repository.returnInput(null)).isNull();
}
@Test // GH-1212
void queryByEnumTypeIn() {
DummyEntity dummyA = new DummyEntity("dummyA");
dummyA.setDirection(Direction.LEFT);
DummyEntity dummyB = new DummyEntity("dummyB");
dummyB.setDirection(Direction.CENTER);
DummyEntity dummyC = new DummyEntity("dummyC");
dummyC.setDirection(Direction.RIGHT);
repository.saveAll(asList(dummyA, dummyB, dummyC));
assertThat(repository.findByEnumTypeIn(asList(Direction.LEFT, Direction.RIGHT)))
.extracting(DummyEntity::getDirection)
.containsExactlyInAnyOrder(Direction.LEFT, Direction.RIGHT);
}
@Test // GH-1212
void queryByEnumTypeEqual() {
DummyEntity dummyA = new DummyEntity("dummyA");
dummyA.setDirection(Direction.LEFT);
DummyEntity dummyB = new DummyEntity("dummyB");
dummyB.setDirection(Direction.CENTER);
DummyEntity dummyC = new DummyEntity("dummyC");
dummyC.setDirection(Direction.RIGHT);
repository.saveAll(asList(dummyA, dummyB, dummyC));
assertThat(repository.findByEnumType(Direction.CENTER))
.extracting(DummyEntity::getDirection)
.containsExactlyInAnyOrder(Direction.CENTER);
}
private Instant createDummyBeforeAndAfterNow() {
Instant now = Instant.now();
@@ -660,6 +694,12 @@ public class JdbcRepositoryIntegrationTests {
@Query("SELECT CAST(:hello AS CHAR(5)) FROM DUMMY_ENTITY")
@Nullable
String returnInput(@Nullable String hello);
@Query("SELECT * FROM DUMMY_ENTITY WHERE DIRECTION IN (:directions)")
List<DummyEntity> findByEnumTypeIn(List<Direction> directions);
@Query("SELECT * FROM DUMMY_ENTITY WHERE DIRECTION = :direction")
List<DummyEntity> findByEnumType(Direction direction);
}
@Configuration
@@ -713,12 +753,17 @@ public class JdbcRepositoryIntegrationTests {
@Id private Long idProp;
boolean flag;
AggregateReference<DummyEntity, Long> ref;
Direction direction;
public DummyEntity(String name) {
this.name = name;
}
}
enum Direction {
LEFT, CENTER, RIGHT
}
interface DummyProjection {
String getName();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 the original author or authors.
* Copyright 2020-2022 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.
@@ -15,28 +15,38 @@
*/
package org.springframework.data.jdbc.repository.query;
import static java.util.Arrays.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.sql.JDBCType;
import java.sql.ResultSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jdbc.core.convert.BasicJdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
import org.springframework.data.jdbc.core.convert.JdbcTypeFactory;
import org.springframework.data.jdbc.core.convert.RelationResolver;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
@@ -55,6 +65,7 @@ import org.springframework.util.ReflectionUtils;
* @author Evgeni Dimitrov
* @author Mark Paluch
* @author Dennis Effing
* @author Chirag Tailor
*/
class StringBasedJdbcQueryUnitTests {
@@ -64,7 +75,7 @@ class StringBasedJdbcQueryUnitTests {
JdbcConverter converter;
@BeforeEach
void setup() throws NoSuchMethodException {
void setup() {
this.defaultRowMapper = mock(RowMapper.class);
this.operations = mock(NamedParameterJdbcOperations.class);
@@ -172,6 +183,54 @@ class StringBasedJdbcQueryUnitTests {
.hasMessageContaining("Page queries are not supported using string-based queries");
}
@Test // GH-1212
void convertsEnumCollectionParameterIntoStringCollectionParameter() {
JdbcQueryMethod queryMethod = createMethod("findByEnumTypeIn", Set.class);
BasicJdbcConverter converter = new BasicJdbcConverter(mock(RelationalMappingContext.class), mock(RelationResolver.class));
StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, result -> mock(RowMapper.class), converter);
query.execute(new Object[] { asList(Direction.LEFT, Direction.RIGHT) });
ArgumentCaptor<SqlParameterSource> captor = ArgumentCaptor.forClass(SqlParameterSource.class);
verify(operations).query(anyString(), captor.capture(), any(ResultSetExtractor.class));
SqlParameterSource sqlParameterSource = captor.getValue();
assertThat(sqlParameterSource.getValue("directions")).asList().containsExactlyInAnyOrder("LEFT", "RIGHT");
}
@Test // GH-1212
void convertsEnumCollectionParameterUsingCustomConverterWhenRegisteredForType() {
JdbcQueryMethod queryMethod = createMethod("findByEnumTypeIn", Set.class);
BasicJdbcConverter converter = new BasicJdbcConverter(mock(RelationalMappingContext.class), mock(RelationResolver.class), new JdbcCustomConversions(asList(DirectionToIntegerConverter.INSTANCE, IntegerToDirectionConverter.INSTANCE)), JdbcTypeFactory.unsupported(), IdentifierProcessing.ANSI);
StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, result -> mock(RowMapper.class), converter);
query.execute(new Object[] { asList(Direction.LEFT, Direction.RIGHT) });
ArgumentCaptor<SqlParameterSource> captor = ArgumentCaptor.forClass(SqlParameterSource.class);
verify(operations).query(anyString(), captor.capture(), any(ResultSetExtractor.class));
SqlParameterSource sqlParameterSource = captor.getValue();
assertThat(sqlParameterSource.getValue("directions")).asList().containsExactlyInAnyOrder(-1, 1);
}
@Test // GH-1212
void doesNotConvertNonCollectionParameter() {
JdbcQueryMethod queryMethod = createMethod("findBySimpleValue", Integer.class);
BasicJdbcConverter converter = new BasicJdbcConverter(mock(RelationalMappingContext.class), mock(RelationResolver.class));
StringBasedJdbcQuery query = new StringBasedJdbcQuery(queryMethod, operations, result -> mock(RowMapper.class), converter);
query.execute(new Object[] { 1 });
ArgumentCaptor<SqlParameterSource> captor = ArgumentCaptor.forClass(SqlParameterSource.class);
verify(operations).query(anyString(), captor.capture(), any(ResultSetExtractor.class));
SqlParameterSource sqlParameterSource = captor.getValue();
assertThat(sqlParameterSource.getValue("value")).isEqualTo(1);
}
private JdbcQueryMethod createMethod(String methodName, Class<?>... paramTypes) {
Method method = ReflectionUtils.findMethod(MyRepository.class, methodName, paramTypes);
@@ -212,6 +271,11 @@ class StringBasedJdbcQueryUnitTests {
@Query(value = "some sql statement")
Slice<Object> sliceAll(Pageable pageable);
@Query(value = "some sql statement")
List<Object> findByEnumTypeIn(Set<Direction> directions);
@Query(value = "some sql statement")
List<Object> findBySimpleValue(Integer value);
}
private static class CustomRowMapper implements RowMapper<Object> {
@@ -241,6 +305,54 @@ class StringBasedJdbcQueryUnitTests {
}
}
private enum Direction {
LEFT, CENTER, RIGHT
}
@WritingConverter
enum DirectionToIntegerConverter implements Converter<Direction, JdbcValue> {
INSTANCE;
@Override
public JdbcValue convert(Direction source) {
int integer;
switch (source) {
case LEFT:
integer = -1;
break;
case CENTER:
integer = 0;
break;
case RIGHT:
integer = 1;
break;
default:
throw new IllegalArgumentException();
}
return JdbcValue.of(integer, JDBCType.INTEGER);
}
}
@ReadingConverter
enum IntegerToDirectionConverter implements Converter<Integer, Direction> {
INSTANCE;
@Override
public Direction convert(Integer source) {
if (source == 0) {
return Direction.CENTER;
} else if (source < 0) {
return Direction.LEFT;
} else {
return Direction.RIGHT;
}
}
}
private static class DummyEntity {
private Long id;

View File

@@ -1,5 +1,5 @@
DROP TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL;
DROP TABLE OTHER_ENTITY;
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -1,2 +1,2 @@
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID IDENTITY PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -1,3 +1,3 @@
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID IDENTITY PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -1,2 +1,2 @@
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT AUTO_INCREMENT PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT AUTO_INCREMENT PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -1,5 +1,5 @@
DROP TABLE OTHER_ENTITY;
DROP TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL;
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id BIGINT IDENTITY PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID BIGINT IDENTITY PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -1,2 +1,2 @@
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -3,7 +3,8 @@ DROP TABLE OTHER_ENTITY CASCADE CONSTRAINTS PURGE;
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL (
ID NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
STRINGY_NUMBER DECIMAL(20,10)
STRINGY_NUMBER DECIMAL(20,10),
DIRECTION INTEGER
);
CREATE TABLE OTHER_ENTITY (

View File

@@ -1,2 +1,2 @@
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id SERIAL PRIMARY KEY, Stringy_number DECIMAL(20,10));
CREATE TABLE ENTITY_WITH_STRINGY_BIG_DECIMAL ( id SERIAL PRIMARY KEY, Stringy_number DECIMAL(20,10), DIRECTION INTEGER);
CREATE TABLE OTHER_ENTITY ( ID SERIAL PRIMARY KEY, CREATED DATE, ENTITY_WITH_STRINGY_BIG_DECIMAL INTEGER);

View File

@@ -7,5 +7,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP, -- with time zone is only supported with z/OS
FLAG BOOLEAN,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -5,5 +5,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -5,5 +5,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -5,5 +5,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME TIMESTAMP(3),
OFFSET_DATE_TIME TIMESTAMP(3),
FLAG BOOLEAN,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -6,5 +6,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME DATETIME,
OFFSET_DATE_TIME DATETIMEOFFSET,
FLAG BIT,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -8,5 +8,6 @@ CREATE TABLE DUMMY_ENTITY
POINT_IN_TIME TIMESTAMP(3) DEFAULT NULL,
OFFSET_DATE_TIME TIMESTAMP(3) DEFAULT NULL,
FLAG BIT(1),
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -7,5 +7,6 @@ CREATE TABLE DUMMY_ENTITY
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG NUMBER(1,0),
REF NUMBER
REF NUMBER,
DIRECTION VARCHAR2(100)
);

View File

@@ -6,5 +6,6 @@ CREATE TABLE dummy_entity
POINT_IN_TIME TIMESTAMP,
OFFSET_DATE_TIME TIMESTAMP WITH TIME ZONE,
FLAG BOOLEAN,
REF BIGINT
REF BIGINT,
DIRECTION VARCHAR(100)
);

View File

@@ -16,9 +16,11 @@
package org.springframework.data.relational.repository.query;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.data.relational.repository.query.RelationalParameters.RelationalParameter;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
@@ -65,9 +67,12 @@ public class RelationalParameters extends Parameters<RelationalParameters, Relat
* Custom {@link Parameter} implementation.
*
* @author Mark Paluch
* @author Chirag Tailor
*/
public static class RelationalParameter extends Parameter {
private final MethodParameter parameter;
/**
* Creates a new {@link RelationalParameter}.
*
@@ -75,6 +80,13 @@ public class RelationalParameters extends Parameters<RelationalParameters, Relat
*/
RelationalParameter(MethodParameter parameter) {
super(parameter);
this.parameter = parameter;
}
public ResolvableType getResolvableType() {
return ResolvableType
.forClassWithGenerics(super.getType(), ResolvableType.forMethodParameter(this.parameter).getGenerics());
}
}
}