Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b91dcf5

Browse files
committed
GH-2020 Added SqlTypeResolver abstraction
Signed-off-by: mipo256 <mikhailpolivakha@gmail.com>
1 parent e82befd commit b91dcf5

File tree

12 files changed

+503
-19
lines changed

12 files changed

+503
-19
lines changed

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcParameters.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,47 @@
2121
import org.springframework.core.MethodParameter;
2222
import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
2323
import org.springframework.data.jdbc.support.JdbcUtil;
24+
import org.springframework.data.relational.core.dialect.DefaultSqlTypeResolver;
25+
import org.springframework.data.relational.core.dialect.SqlTypeResolver;
2426
import org.springframework.data.relational.repository.query.RelationalParameters;
2527
import org.springframework.data.repository.query.Parameter;
2628
import org.springframework.data.repository.query.ParametersSource;
2729
import org.springframework.data.util.Lazy;
2830
import org.springframework.data.util.TypeInformation;
31+
import org.springframework.util.Assert;
2932

3033
/**
3134
* Custom extension of {@link RelationalParameters}.
3235
*
3336
* @author Mark Paluch
37+
* @author Mikhail Polivakha
3438
* @since 3.2.6
3539
*/
3640
public class JdbcParameters extends RelationalParameters {
3741

3842
/**
39-
* Creates a new {@link JdbcParameters} instance from the given {@link ParametersSource}.
43+
* Creates a new {@link JdbcParameters} instance from the given {@link ParametersSource}. Uses the {@link DefaultSqlTypeResolver}.
4044
*
4145
* @param parametersSource must not be {@literal null}.
4246
*/
4347
public JdbcParameters(ParametersSource parametersSource) {
4448
super(parametersSource,
45-
methodParameter -> new JdbcParameter(methodParameter, parametersSource.getDomainTypeInformation()));
49+
methodParameter -> new JdbcParameter(methodParameter, parametersSource.getDomainTypeInformation(),
50+
Lazy.of(DefaultSqlTypeResolver.INSTANCE)));
51+
}
52+
53+
/**
54+
* Creates a new {@link JdbcParameters} instance from the given {@link ParametersSource} and given {@link SqlTypeResolver}.
55+
*
56+
* @param parametersSource must not be {@literal null}.
57+
* @param sqlTypeResolver must not be {@literal null}.
58+
*/
59+
public JdbcParameters(ParametersSource parametersSource, Lazy<SqlTypeResolver> sqlTypeResolver) {
60+
super(parametersSource,
61+
methodParameter -> new JdbcParameter(methodParameter, parametersSource.getDomainTypeInformation(), sqlTypeResolver));
62+
63+
Assert.notNull(sqlTypeResolver, "SqlTypeResolver must not be null");
64+
Assert.notNull(parametersSource, "ParametersSource must not be null");
4665
}
4766

4867
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -69,27 +88,42 @@ protected JdbcParameters createFrom(List<RelationalParameter> parameters) {
6988
*/
7089
public static class JdbcParameter extends RelationalParameter {
7190

72-
private final SQLType sqlType;
91+
private final Lazy<SQLType> sqlType;
7392
private final Lazy<SQLType> actualSqlType;
7493

7594
/**
7695
* Creates a new {@link RelationalParameter}.
7796
*
7897
* @param parameter must not be {@literal null}.
7998
*/
80-
JdbcParameter(MethodParameter parameter, TypeInformation<?> domainType) {
99+
JdbcParameter(MethodParameter parameter, TypeInformation<?> domainType, Lazy<SqlTypeResolver> sqlTypeResolver) {
81100
super(parameter, domainType);
82101

83102
TypeInformation<?> typeInformation = getTypeInformation();
84103

85-
sqlType = JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(typeInformation.getType()));
104+
sqlType = Lazy.of(() -> {
105+
SQLType resolvedSqlType = sqlTypeResolver.get().resolveSqlType(this);
106+
107+
if (resolvedSqlType == null) {
108+
return JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(typeInformation.getType()));
109+
} else {
110+
return resolvedSqlType;
111+
}
112+
});
113+
114+
actualSqlType = Lazy.of(() -> {
115+
SQLType resolvedActualSqlType = sqlTypeResolver.get().resolveActualSqlType(this);
86116

87-
actualSqlType = Lazy.of(() -> JdbcUtil
88-
.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(typeInformation.getActualType().getType())));
117+
if (resolvedActualSqlType == null) {
118+
return JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(typeInformation.getActualType().getType()));
119+
} else {
120+
return resolvedActualSqlType;
121+
}
122+
});
89123
}
90124

91125
public SQLType getSqlType() {
92-
return sqlType;
126+
return sqlType.get();
93127
}
94128

95129
public SQLType getActualSqlType() {

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethod.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,28 @@
1717

1818
import java.lang.annotation.Annotation;
1919
import java.lang.reflect.Method;
20+
import java.util.List;
2021
import java.util.Map;
2122
import java.util.Optional;
2223

2324
import org.springframework.core.annotation.AnnotatedElementUtils;
2425
import org.springframework.core.annotation.AnnotationUtils;
2526
import org.springframework.data.mapping.context.MappingContext;
2627
import org.springframework.data.projection.ProjectionFactory;
28+
import org.springframework.data.relational.core.dialect.DefaultSqlTypeResolver;
29+
import org.springframework.data.relational.core.dialect.SqlTypeResolver;
2730
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
2831
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2932
import org.springframework.data.relational.repository.Lock;
3033
import org.springframework.data.relational.repository.query.RelationalEntityMetadata;
3134
import org.springframework.data.relational.repository.query.SimpleRelationalEntityMetadata;
3235
import org.springframework.data.repository.core.NamedQueries;
3336
import org.springframework.data.repository.core.RepositoryMetadata;
37+
import org.springframework.data.repository.query.Parameter;
3438
import org.springframework.data.repository.query.Parameters;
3539
import org.springframework.data.repository.query.ParametersSource;
3640
import org.springframework.data.repository.query.QueryMethod;
41+
import org.springframework.data.util.Lazy;
3742
import org.springframework.jdbc.core.ResultSetExtractor;
3843
import org.springframework.jdbc.core.RowMapper;
3944
import org.springframework.lang.Nullable;
@@ -53,6 +58,8 @@
5358
* @author Diego Krupitza
5459
* @author Mark Paluch
5560
* @author Daeho Kwon
61+
* @author Mikhail Polivakha
62+
>>>>>>> d92a7298 (GH-2020 Added SqlTypeResolver abstraction)
5663
*/
5764
public class JdbcQueryMethod extends QueryMethod {
5865

@@ -63,17 +70,33 @@ public class JdbcQueryMethod extends QueryMethod {
6370
private @Nullable RelationalEntityMetadata<?> metadata;
6471
private final boolean modifyingQuery;
6572

73+
private final SqlTypeResolver sqlTypeResolver;
74+
6675
// TODO: Remove NamedQueries and put it into JdbcQueryLookupStrategy
6776
public JdbcQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
6877
NamedQueries namedQueries,
6978
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext) {
79+
this(method, metadata, factory, namedQueries, mappingContext, DefaultSqlTypeResolver.INSTANCE);
80+
}
81+
82+
public JdbcQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
83+
NamedQueries namedQueries,
84+
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext,
85+
SqlTypeResolver sqlTypeResolver) {
7086

7187
super(method, metadata, factory, JdbcParameters::new);
7288
this.namedQueries = namedQueries;
7389
this.method = method;
7490
this.mappingContext = mappingContext;
7591
this.annotationCache = new ConcurrentReferenceHashMap<>();
7692
this.modifyingQuery = AnnotationUtils.findAnnotation(method, Modifying.class) != null;
93+
this.sqlTypeResolver = sqlTypeResolver;
94+
}
95+
96+
// SqlTypeResolver has to be wrapped, because the createParameters() is invoked in the parents constructor before child initialization
97+
@Override
98+
protected Parameters<?, ?> createParameters(ParametersSource parametersSource) {
99+
return new JdbcParameters(parametersSource, Lazy.of(() -> this.sqlTypeResolver));
77100
}
78101

79102
@Override

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.data.jdbc.core.convert.JdbcConverter;
3636
import org.springframework.data.jdbc.core.mapping.JdbcValue;
3737
import org.springframework.data.jdbc.support.JdbcUtil;
38+
import org.springframework.data.relational.core.dialect.SqlTypeResolver;
3839
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3940
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
4041
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
@@ -85,7 +86,11 @@ public class StringBasedJdbcQuery extends AbstractJdbcQuery {
8586

8687
/**
8788
* Creates a new {@link StringBasedJdbcQuery} for the given {@link JdbcQueryMethod}, {@link RelationalMappingContext}
89+
<<<<<<< HEAD
8890
* and {@link org.springframework.data.jdbc.repository.query.RowMapperFactory}.
91+
=======
92+
* and {@link RowMapperFactory}.
93+
>>>>>>> d92a7298 (GH-2020 Added SqlTypeResolver abstraction)
8994
*
9095
* @param queryMethod must not be {@literal null}.
9196
* @param operations must not be {@literal null}.
@@ -154,6 +159,10 @@ public StringBasedJdbcQuery(String query, JdbcQueryMethod queryMethod, NamedPara
154159
this.delegate = delegate;
155160
}
156161

162+
<<<<<<< HEAD
163+
=======
164+
165+
>>>>>>> d92a7298 (GH-2020 Added SqlTypeResolver abstraction)
157166
@Override
158167
public Object execute(Object[] objects) {
159168

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public RepositoryQuery resolveQuery(Method method, RepositoryMetadata repository
222222
*/
223223
JdbcQueryMethod getJdbcQueryMethod(Method method, RepositoryMetadata repositoryMetadata,
224224
ProjectionFactory projectionFactory, NamedQueries namedQueries) {
225-
return new JdbcQueryMethod(method, repositoryMetadata, projectionFactory, namedQueries, getMappingContext());
225+
return new JdbcQueryMethod(method, repositoryMetadata, projectionFactory, namedQueries, getMappingContext(), getDialect().getSqlTypeResolver());
226226
}
227227

228228
/**

‎spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/JdbcQueryMethodUnitTests.java

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,23 @@
2020
import static org.mockito.Mockito.*;
2121

2222
import java.lang.reflect.Method;
23+
import java.sql.JDBCType;
2324
import java.sql.ResultSet;
25+
import java.sql.SQLType;
26+
import java.sql.Types;
27+
import java.util.List;
2428
import java.util.Properties;
2529

30+
import org.assertj.core.api.Assertions;
2631
import org.junit.jupiter.api.BeforeEach;
2732
import org.junit.jupiter.api.Test;
2833
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
2934
import org.springframework.data.projection.ProjectionFactory;
35+
import org.springframework.data.relational.core.dialect.DefaultSqlTypeResolver;
36+
import org.springframework.data.relational.core.dialect.SqlTypeResolver;
3037
import org.springframework.data.relational.core.sql.LockMode;
3138
import org.springframework.data.relational.repository.Lock;
39+
import org.springframework.data.relational.repository.query.SqlType;
3240
import org.springframework.data.repository.core.NamedQueries;
3341
import org.springframework.data.repository.core.RepositoryMetadata;
3442
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
@@ -43,6 +51,7 @@
4351
* @author Moises Cisneros
4452
* @author Mark Paluch
4553
* @author Diego Krupitza
54+
* @author Mikhail Polivakha
4655
*/
4756
public class JdbcQueryMethodUnitTests {
4857

@@ -66,6 +75,8 @@ public void before() {
6675
namedQueries = new PropertiesBasedNamedQueries(properties);
6776

6877
metadata = mock(RepositoryMetadata.class);
78+
when(metadata.getDomainTypeInformation()).then(invocationOnMock -> TypeInformation.of(Object.class));
79+
6980
doReturn(String.class).when(metadata).getReturnedDomainClass(any(Method.class));
7081
doReturn(TypeInformation.of(String.class)).when(metadata).getReturnType(any(Method.class));
7182
}
@@ -78,6 +89,31 @@ public void returnsSqlStatement() throws NoSuchMethodException {
7889
assertThat(queryMethod.getDeclaredQuery()).isEqualTo(QUERY);
7990
}
8091

92+
@Test // DATAJDBC-165
93+
public void testSqlTypeResolver() throws NoSuchMethodException {
94+
95+
JdbcQueryMethod queryMethod = createJdbcQueryMethod(
96+
"findUserTestMethod",
97+
new DefaultSqlTypeResolver(),
98+
Integer.class, String.class, List.class
99+
);
100+
101+
JdbcParameters parameters = queryMethod.getParameters();
102+
103+
SQLType first = parameters.getParameter(0).getSqlType();
104+
SQLType second = parameters.getParameter(1).getSqlType();
105+
SQLType thirdActual = parameters.getParameter(2).getActualSqlType();
106+
107+
Assertions.assertThat(first.getName()).isEqualTo(JDBCType.TINYINT.getName());
108+
Assertions.assertThat(first.getVendorTypeNumber()).isEqualTo(Types.TINYINT);
109+
110+
Assertions.assertThat(second.getName()).isEqualTo(JDBCType.VARCHAR.getName());
111+
Assertions.assertThat(second.getVendorTypeNumber()).isEqualTo(Types.VARCHAR);
112+
113+
Assertions.assertThat(thirdActual.getName()).isEqualTo(JDBCType.SMALLINT.getName());
114+
Assertions.assertThat(thirdActual.getVendorTypeNumber()).isEqualTo(Types.SMALLINT);
115+
}
116+
81117
@Test // DATAJDBC-165
82118
public void returnsSpecifiedRowMapperClass() throws NoSuchMethodException {
83119

@@ -102,12 +138,6 @@ public void returnsSpecifiedSqlStatementIfNameAndValueAreGiven() throws NoSuchMe
102138

103139
}
104140

105-
private JdbcQueryMethod createJdbcQueryMethod(String methodName) throws NoSuchMethodException {
106-
107-
Method method = JdbcQueryMethodUnitTests.class.getDeclaredMethod(methodName);
108-
return new JdbcQueryMethod(method, metadata, mock(ProjectionFactory.class), namedQueries, mappingContext);
109-
}
110-
111141
@Test // DATAJDBC-234
112142
public void returnsImplicitlyNamedQuery() throws NoSuchMethodException {
113143

@@ -148,10 +178,27 @@ void returnsQueryMethodWithCorrectLockTypeNoLock() throws NoSuchMethodException
148178
assertThat(queryMethodWithWriteLock.lookupLockAnnotation()).isEmpty();
149179
}
150180

181+
private JdbcQueryMethod createJdbcQueryMethod(String methodName) throws NoSuchMethodException {
182+
return createJdbcQueryMethod(methodName, new DefaultSqlTypeResolver());
183+
}
184+
185+
private JdbcQueryMethod createJdbcQueryMethod(String methodName, SqlTypeResolver sqlTypeResolver, Class<?>... args) throws NoSuchMethodException {
186+
187+
Method method = JdbcQueryMethodUnitTests.class.getDeclaredMethod(methodName, args);
188+
return new JdbcQueryMethod(method, metadata, mock(ProjectionFactory.class), namedQueries, mappingContext, sqlTypeResolver);
189+
}
190+
151191
@Lock(LockMode.PESSIMISTIC_WRITE)
152192
@Query
153193
private void queryMethodWithWriteLock() {}
154194

195+
@Query
196+
private void findUserTestMethod(
197+
@SqlType(name = "TINYINT", vendorTypeNumber = Types.TINYINT) Integer age,
198+
String name,
199+
List<@SqlType(name = "SMALLINT", vendorTypeNumber = Types.SMALLINT) Integer> statuses
200+
) {}
201+
155202
@Lock(LockMode.PESSIMISTIC_READ)
156203
@Query
157204
private void queryMethodWithReadLock() {}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /