Browse Source

DATAJDBC-318 - Fixed the generation of the select list.

The select list must include columns for 1:1 relationships.

The implementation is copied from SqlGenerator and will be unified in the near future.

Original pull request: #209.
pull/210/head
Jens Schauder 6 years ago
parent
commit
d80614b4d8
No known key found for this signature in database
GPG Key ID: 996B1389BA0721C3
  1. 175
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java
  2. 14
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQuery.java
  3. 70
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/SqlContext.java
  4. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java
  5. 28
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedWithReferenceIntegrationTests.java
  6. 121
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java
  7. 3
      spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java

175
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/JdbcQueryCreator.java

@ -15,7 +15,9 @@
*/ */
package org.springframework.data.jdbc.repository.query; package org.springframework.data.jdbc.repository.query;
import java.util.Collections; import lombok.Value;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -26,13 +28,15 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.RenderContextFactory; import org.springframework.data.relational.core.dialect.RenderContextFactory;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension; import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
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.RelationalPersistentProperty; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.query.Criteria; import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.sql.Column;
import org.springframework.data.relational.core.sql.Expression; import org.springframework.data.relational.core.sql.Expression;
import org.springframework.data.relational.core.sql.Select; import org.springframework.data.relational.core.sql.Select;
import org.springframework.data.relational.core.sql.SelectBuilder; import org.springframework.data.relational.core.sql.SelectBuilder;
import org.springframework.data.relational.core.sql.SqlIdentifier; import org.springframework.data.relational.core.sql.StatementBuilder;
import org.springframework.data.relational.core.sql.Table; import org.springframework.data.relational.core.sql.Table;
import org.springframework.data.relational.core.sql.render.SqlRenderer; import org.springframework.data.relational.core.sql.render.SqlRenderer;
import org.springframework.data.relational.repository.query.RelationalEntityMetadata; import org.springframework.data.relational.repository.query.RelationalEntityMetadata;
@ -42,16 +46,19 @@ import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.parser.Part; import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree; import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Implementation of {@link RelationalQueryCreator} that creates {@link ParametrizedQuery} from a {@link PartTree}. * Implementation of {@link RelationalQueryCreator} that creates {@link ParametrizedQuery} from a {@link PartTree}.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Jens Schauder
* @since 2.0 * @since 2.0
*/ */
class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> { class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
private final RelationalMappingContext context;
private final PartTree tree; private final PartTree tree;
private final RelationalParameterAccessor accessor; private final RelationalParameterAccessor accessor;
private final QueryMapper queryMapper; private final QueryMapper queryMapper;
@ -62,20 +69,22 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
* Creates new instance of this class with the given {@link PartTree}, {@link JdbcConverter}, {@link Dialect}, * Creates new instance of this class with the given {@link PartTree}, {@link JdbcConverter}, {@link Dialect},
* {@link RelationalEntityMetadata} and {@link RelationalParameterAccessor}. * {@link RelationalEntityMetadata} and {@link RelationalParameterAccessor}.
* *
* @param context
* @param tree part tree, must not be {@literal null}. * @param tree part tree, must not be {@literal null}.
* @param converter must not be {@literal null}. * @param converter must not be {@literal null}.
* @param dialect must not be {@literal null}. * @param dialect must not be {@literal null}.
* @param entityMetadata relational entity metadata, must not be {@literal null}. * @param entityMetadata relational entity metadata, must not be {@literal null}.
* @param accessor parameter metadata provider, must not be {@literal null}. * @param accessor parameter metadata provider, must not be {@literal null}.
*/ */
JdbcQueryCreator(PartTree tree, JdbcConverter converter, Dialect dialect, RelationalEntityMetadata<?> entityMetadata, JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
RelationalParameterAccessor accessor) { RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor) {
super(tree, accessor); super(tree, accessor);
Assert.notNull(converter, "JdbcConverter must not be null"); Assert.notNull(converter, "JdbcConverter must not be null");
Assert.notNull(dialect, "Dialect must not be null"); Assert.notNull(dialect, "Dialect must not be null");
Assert.notNull(entityMetadata, "Relational entity metadata must not be null"); Assert.notNull(entityMetadata, "Relational entity metadata must not be null");
this.context = context;
this.tree = tree; this.tree = tree;
this.accessor = accessor; this.accessor = accessor;
@ -91,7 +100,7 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
* @param tree * @param tree
* @param parameters * @param parameters
*/ */
public static void validate(PartTree tree, Parameters<?, ?> parameters, static void validate(PartTree tree, Parameters<?, ?> parameters,
MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context) { MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> context) {
RelationalQueryCreator.validate(tree, parameters); RelationalQueryCreator.validate(tree, parameters);
@ -141,53 +150,167 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
* @return instance of {@link ParametrizedQuery} * @return instance of {@link ParametrizedQuery}
*/ */
@Override @Override
protected ParametrizedQuery complete(Criteria criteria, Sort sort) { protected ParametrizedQuery complete(@Nullable Criteria criteria, Sort sort) {
RelationalPersistentEntity<?> entity = entityMetadata.getTableEntity(); RelationalPersistentEntity<?> entity = entityMetadata.getTableEntity();
Table table = Table.create(entityMetadata.getTableName()); Table table = Table.create(entityMetadata.getTableName());
MapSqlParameterSource parameterSource = new MapSqlParameterSource(); MapSqlParameterSource parameterSource = new MapSqlParameterSource();
List<? extends Expression> columns = table.columns(getSelectProjection()); SelectBuilder.SelectLimitOffset limitOffsetBuilder = createSelectClause(entity, table);
if (columns.isEmpty()) { SelectBuilder.SelectWhere whereBuilder = applyLimitAndOffset(limitOffsetBuilder);
columns = Collections.singletonList(table.asterisk()); SelectBuilder.SelectOrdered selectOrderBuilder = applyCriteria(criteria, entity, table, parameterSource,
} whereBuilder);
selectOrderBuilder = applyOrderBy(sort, entity, table, selectOrderBuilder);
Select select = selectOrderBuilder.build();
String sql = SqlRenderer.create(renderContextFactory.createRenderContext()).render(select);
return new ParametrizedQuery(sql, parameterSource);
}
private SelectBuilder.SelectOrdered applyOrderBy(Sort sort, RelationalPersistentEntity<?> entity, Table table,
SelectBuilder.SelectOrdered selectOrdered) {
return sort.isSorted() ? //
selectOrdered.orderBy(queryMapper.getMappedSort(table, sort, entity)) //
: selectOrdered;
}
private SelectBuilder.SelectOrdered applyCriteria(@Nullable Criteria criteria, RelationalPersistentEntity<?> entity,
Table table, MapSqlParameterSource parameterSource, SelectBuilder.SelectWhere whereBuilder) {
return criteria != null //
? whereBuilder.where(queryMapper.getMappedObject(parameterSource, criteria, table, entity)) //
: whereBuilder;
}
SelectBuilder.SelectFromAndJoin builder = Select.builder().select(columns).from(table); private SelectBuilder.SelectWhere applyLimitAndOffset(SelectBuilder.SelectLimitOffset limitOffsetBuilder) {
if (tree.isExistsProjection()) { if (tree.isExistsProjection()) {
builder = builder.limit(1); limitOffsetBuilder = limitOffsetBuilder.limit(1);
} else if (tree.isLimiting()) { } else if (tree.isLimiting()) {
builder = builder.limit(tree.getMaxResults()); limitOffsetBuilder = limitOffsetBuilder.limit(tree.getMaxResults());
} }
Pageable pageable = accessor.getPageable(); Pageable pageable = accessor.getPageable();
if (pageable.isPaged()) { if (pageable.isPaged()) {
builder = builder.limit(pageable.getPageSize()).offset(pageable.getOffset()); limitOffsetBuilder = limitOffsetBuilder.limit(pageable.getPageSize()).offset(pageable.getOffset());
} }
if (criteria != null) { return (SelectBuilder.SelectWhere) limitOffsetBuilder;
builder.where(queryMapper.getMappedObject(parameterSource, criteria, table, entity)); }
private SelectBuilder.SelectLimitOffset createSelectClause(RelationalPersistentEntity<?> entity, Table table) {
SelectBuilder.SelectJoin builder;
if (tree.isExistsProjection()) {
Column idColumn = table.column(entity.getIdColumn());
builder = Select.builder().select(idColumn).from(table);
} else {
builder = selectBuilder(table);
} }
if (sort.isSorted()) { return (SelectBuilder.SelectLimitOffset) builder;
builder.orderBy(queryMapper.getMappedSort(table, sort, entity)); }
private SelectBuilder.SelectJoin selectBuilder(Table table) {
List<Expression> columnExpressions = new ArrayList<>();
RelationalPersistentEntity<?> entity = entityMetadata.getTableEntity();
SqlContext sqlContext = new SqlContext(entity);
List<Join> joinTables = new ArrayList<>();
for (PersistentPropertyPath<RelationalPersistentProperty> path : context
.findPersistentPropertyPaths(entity.getType(), p -> true)) {
PersistentPropertyPathExtension extPath = new PersistentPropertyPathExtension(context, path);
// add a join if necessary
Join join = getJoin(sqlContext, extPath);
if (join != null) {
joinTables.add(join);
}
Column column = getColumn(sqlContext, extPath);
if (column != null) {
columnExpressions.add(column);
}
} }
Select select = builder.build(); SelectBuilder.SelectAndFrom selectBuilder = StatementBuilder.select(columnExpressions);
SelectBuilder.SelectJoin baseSelect = selectBuilder.from(table);
String sql = SqlRenderer.create(renderContextFactory.createRenderContext()).render(select); for (Join join : joinTables) {
baseSelect = baseSelect.leftOuterJoin(join.joinTable).on(join.joinColumn).equals(join.parentId);
}
return new ParametrizedQuery(sql, parameterSource); return baseSelect;
} }
private SqlIdentifier[] getSelectProjection() { /**
* Create a {@link Column} for {@link PersistentPropertyPathExtension}.
*
* @param sqlContext
* @param path the path to the column in question.
* @return the statement as a {@link String}. Guaranteed to be not {@literal null}.
*/
@Nullable
private Column getColumn(SqlContext sqlContext, PersistentPropertyPathExtension path) {
// an embedded itself doesn't give an column, its members will though.
// if there is a collection or map on the path it won't get selected at all, but it will get loaded with a separate
// select
// only the parent path is considered in order to handle arrays that get stored as BINARY properly
if (path.isEmbedded() || path.getParentPath().isMultiValued()) {
return null;
}
RelationalPersistentEntity<?> tableEntity = entityMetadata.getTableEntity(); if (path.isEntity()) {
if (tree.isExistsProjection()) { // Simple entities without id include there backreference as an synthetic id in order to distinguish null entities
return new SqlIdentifier[] { tableEntity.getIdColumn() }; // from entities with only null values.
if (path.isQualified() //
|| path.isCollectionLike() //
|| path.hasIdProperty() //
) {
return null;
}
return sqlContext.getReverseColumn(path);
}
return sqlContext.getColumn(path);
}
@Nullable
Join getJoin(SqlContext sqlContext, PersistentPropertyPathExtension path) {
if (!path.isEntity() || path.isEmbedded() || path.isMultiValued()) {
return null;
} }
return new SqlIdentifier[0]; Table currentTable = sqlContext.getTable(path);
PersistentPropertyPathExtension idDefiningParentPath = path.getIdDefiningParentPath();
Table parentTable = sqlContext.getTable(idDefiningParentPath);
return new Join( //
currentTable, //
currentTable.column(path.getReverseColumnName()), //
parentTable.column(idDefiningParentPath.getIdColumnName()) //
);
}
/**
* Value object representing a {@code JOIN} association.
*/
@Value
static private class Join {
Table joinTable;
Column joinColumn;
Column parentId;
} }
} }

14
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQuery.java

@ -18,6 +18,7 @@ package org.springframework.data.jdbc.repository.query;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.relational.core.dialect.Dialect; import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.repository.query.RelationalEntityMetadata; import org.springframework.data.relational.repository.query.RelationalEntityMetadata;
import org.springframework.data.relational.repository.query.RelationalParameterAccessor; import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor; import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
@ -31,10 +32,12 @@ import org.springframework.util.Assert;
* An {@link AbstractJdbcQuery} implementation based on a {@link PartTree}. * An {@link AbstractJdbcQuery} implementation based on a {@link PartTree}.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Jens Schauder
* @since 2.0 * @since 2.0
*/ */
public class PartTreeJdbcQuery extends AbstractJdbcQuery { public class PartTreeJdbcQuery extends AbstractJdbcQuery {
private final RelationalMappingContext context;
private final Parameters<?, ?> parameters; private final Parameters<?, ?> parameters;
private final Dialect dialect; private final Dialect dialect;
private final JdbcConverter converter; private final JdbcConverter converter;
@ -43,22 +46,25 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
/** /**
* Creates a new {@link PartTreeJdbcQuery}. * Creates a new {@link PartTreeJdbcQuery}.
* *
* @param context must not be {@literal null}.
* @param queryMethod must not be {@literal null}. * @param queryMethod must not be {@literal null}.
* @param dialect must not be {@literal null}. * @param dialect must not be {@literal null}.
* @param converter must not be {@literal null}. * @param converter must not be {@literal null}.
* @param operations must not be {@literal null}. * @param operations must not be {@literal null}.
* @param rowMapper must not be {@literal null}. * @param rowMapper must not be {@literal null}.
*/ */
public PartTreeJdbcQuery(JdbcQueryMethod queryMethod, Dialect dialect, JdbcConverter converter, public PartTreeJdbcQuery(RelationalMappingContext context, JdbcQueryMethod queryMethod, Dialect dialect, JdbcConverter converter,
NamedParameterJdbcOperations operations, RowMapper<Object> rowMapper) { NamedParameterJdbcOperations operations, RowMapper<Object> rowMapper) {
super(queryMethod, operations, rowMapper); super(queryMethod, operations, rowMapper);
Assert.notNull(context, "RelationalMappingContext must not be null");
Assert.notNull(queryMethod, "JdbcQueryMethod must not be null"); Assert.notNull(queryMethod, "JdbcQueryMethod must not be null");
Assert.notNull(dialect, "Dialect must not be null"); Assert.notNull(dialect, "Dialect must not be null");
Assert.notNull(converter, "JdbcConverter must not be null"); Assert.notNull(converter, "JdbcConverter must not be null");
this.context = context;
this.parameters = queryMethod.getParameters(); this.parameters = queryMethod.getParameters();
this.dialect = dialect; this.dialect = dialect;
this.converter = converter; this.converter = converter;
@ -90,7 +96,7 @@ public class PartTreeJdbcQuery extends AbstractJdbcQuery {
protected ParametrizedQuery createQuery(RelationalParametersParameterAccessor accessor) { protected ParametrizedQuery createQuery(RelationalParametersParameterAccessor accessor) {
RelationalEntityMetadata<?> entityMetadata = getQueryMethod().getEntityInformation(); RelationalEntityMetadata<?> entityMetadata = getQueryMethod().getEntityInformation();
JdbcQueryCreator queryCreator = new JdbcQueryCreator(tree, converter, dialect, entityMetadata, accessor); JdbcQueryCreator queryCreator = new JdbcQueryCreator(context, tree, converter, dialect, entityMetadata, accessor);
return queryCreator.createQuery(getDynamicSort(accessor)); return queryCreator.createQuery(getDynamicSort(accessor));
} }
} }

70
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/SqlContext.java

@ -0,0 +1,70 @@
/*
* Copyright 2019-2020 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.jdbc.repository.query;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.sql.Column;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.data.relational.core.sql.Table;
/**
* Utility to get from path to SQL DSL elements. This is a temporary class and duplicates
* {@link org.springframework.data.jdbc.core.convert.SqlContext}.
*
* @author Jens Schauder
* @author Mark Paluch
* @author Tyler Van Gorder
* @since 2.0
*/
class SqlContext {
private final RelationalPersistentEntity<?> entity;
private final Table table;
SqlContext(RelationalPersistentEntity<?> entity) {
this.entity = entity;
this.table = Table.create(entity.getTableName());
}
Column getIdColumn() {
return table.column(entity.getIdColumn());
}
Column getVersionColumn() {
return table.column(entity.getRequiredVersionProperty().getColumnName());
}
Table getTable() {
return table;
}
Table getTable(PersistentPropertyPathExtension path) {
SqlIdentifier tableAlias = path.getTableAlias();
Table table = Table.create(path.getTableName());
return tableAlias == null ? table : table.as(tableAlias);
}
Column getColumn(PersistentPropertyPathExtension path) {
return getTable(path).column(path.getColumnName()).as(path.getColumnAlias());
}
Column getReverseColumn(PersistentPropertyPathExtension path) {
return getTable(path).column(path.getReverseColumnName()).as(path.getReverseColumnNameAlias());
}
}

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

@ -101,7 +101,7 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
RowMapper<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod); RowMapper<?> mapper = queryMethod.isModifyingQuery() ? null : createMapper(queryMethod);
return new StringBasedJdbcQuery(queryMethod, operations, mapper, converter); return new StringBasedJdbcQuery(queryMethod, operations, mapper, converter);
} else { } else {
return new PartTreeJdbcQuery(queryMethod, dialect, converter, operations, createMapper(queryMethod)); return new PartTreeJdbcQuery(context, queryMethod, dialect, converter, operations, createMapper(queryMethod));
} }
} catch (Exception e) { } catch (Exception e) {
throw QueryCreationException.create(queryMethod, e.getMessage()); throw QueryCreationException.create(queryMethod, e.getMessage());

28
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedWithReferenceIntegrationTests.java

@ -20,7 +20,7 @@ import static org.assertj.core.api.Assertions.*;
import lombok.Data; import lombok.Data;
import java.sql.SQLException; import java.util.List;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Rule; import org.junit.Rule;
@ -50,6 +50,7 @@ import org.springframework.transaction.annotation.Transactional;
* Very simple use cases for creation and usage of JdbcRepositories with test {@link Embedded} annotation in Entities. * Very simple use cases for creation and usage of JdbcRepositories with test {@link Embedded} annotation in Entities.
* *
* @author Bastian Wilhelm * @author Bastian Wilhelm
* @author Jens Schauder
*/ */
@ContextConfiguration @ContextConfiguration
@Transactional @Transactional
@ -225,7 +226,28 @@ public class JdbcRepositoryEmbeddedWithReferenceIntegrationTests {
assertThat(repository.findAll()).isEmpty(); assertThat(repository.findAll()).isEmpty();
} }
@Test // DATAJDBC-318
public void queryDerivationLoadsReferencedEntitiesCorrectly() {
repository.save(createDummyEntity());
repository.save(createDummyEntity());
DummyEntity saved = repository.save(createDummyEntity());
assertThat(repository.findByTest(saved.test)) //
.extracting( //
e -> e.test, //
e -> e.embeddable.test, //
e -> e.embeddable.dummyEntity2.test //
).containsExactly( //
tuple(saved.test, saved.embeddable.test, saved.embeddable.dummyEntity2.test), //
tuple(saved.test, saved.embeddable.test, saved.embeddable.dummyEntity2.test), //
tuple(saved.test, saved.embeddable.test, saved.embeddable.dummyEntity2.test) //
);
}
private static DummyEntity createDummyEntity() { private static DummyEntity createDummyEntity() {
DummyEntity entity = new DummyEntity(); DummyEntity entity = new DummyEntity();
entity.setTest("root"); entity.setTest("root");
@ -242,7 +264,9 @@ public class JdbcRepositoryEmbeddedWithReferenceIntegrationTests {
return entity; return entity;
} }
interface DummyEntityRepository extends CrudRepository<DummyEntity, Long> {} interface DummyEntityRepository extends CrudRepository<DummyEntity, Long> {
List<DummyEntity> findByTest(String test);
}
@Data @Data
private static class DummyEntity { private static class DummyEntity {

121
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/query/PartTreeJdbcQueryUnitTests.java

@ -30,7 +30,6 @@ import java.util.Properties;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter;
import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcConverter;
@ -61,7 +60,9 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
public class PartTreeJdbcQueryUnitTests { public class PartTreeJdbcQueryUnitTests {
private static final String TABLE = "\"users\""; private static final String TABLE = "\"users\"";
private static final String ALL_FIELDS = "\"users\".*"; private static final String ALL_FIELDS = "\"users\".\"ID\" AS \"ID\", \"users\".\"AGE\" AS \"AGE\", \"hated\".\"USER\" AS \"HATED_USER\", \"users\".\"ACTIVE\" AS \"ACTIVE\", \"users\".\"LAST_NAME\" AS \"LAST_NAME\", \"users\".\"FIRST_NAME\" AS \"FIRST_NAME\", \"users\".\"DATE_OF_BIRTH\" AS \"DATE_OF_BIRTH\", \"users\".\"HOBBY_REFERENCE\" AS \"HOBBY_REFERENCE\", \"hated\".\"NAME\" AS \"HATED_NAME\", \"users\".\"USER_CITY\" AS \"USER_CITY\", \"users\".\"USER_STREET\" AS \"USER_STREET\"";
private static final String JOIN_CLAUSE = "FROM \"users\" LEFT OUTER JOIN \"HOBBY\" AS \"hated\" ON \"hated\".\"USER\" = \"users\".\"ID\"";
private static final String BASE_SELECT = "SELECT " + ALL_FIELDS + " " + JOIN_CLAUSE;
JdbcMappingContext mappingContext = new JdbcMappingContext(); JdbcMappingContext mappingContext = new JdbcMappingContext();
JdbcConverter converter = new BasicJdbcConverter(mappingContext, mock(RelationResolver.class)); JdbcConverter converter = new BasicJdbcConverter(mappingContext, mock(RelationResolver.class));
@ -108,8 +109,7 @@ public class PartTreeJdbcQueryUnitTests {
PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod);
ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "John" })); ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "John" }));
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" = :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" = :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -119,8 +119,7 @@ public class PartTreeJdbcQueryUnitTests {
PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod);
ParametrizedQuery query = jdbcQuery.createQuery((getAccessor(queryMethod, new Object[] { null }))); ParametrizedQuery query = jdbcQuery.createQuery((getAccessor(queryMethod, new Object[] { null })));
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" IS NULL");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" IS NULL");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -141,8 +140,8 @@ public class PartTreeJdbcQueryUnitTests {
PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod);
ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "Doe", "John" })); ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "Doe", "John" }));
assertThat(query.getQuery()).isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"LAST_NAME\" = :last_name AND (" + TABLE
+ ".\"LAST_NAME\" = :last_name AND (" + TABLE + ".\"FIRST_NAME\" = :first_name)"); + ".\"FIRST_NAME\" = :first_name)");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -152,8 +151,8 @@ public class PartTreeJdbcQueryUnitTests {
PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod); PartTreeJdbcQuery jdbcQuery = createQuery(queryMethod);
ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "Doe", "John" })); ParametrizedQuery query = jdbcQuery.createQuery(getAccessor(queryMethod, new Object[] { "Doe", "John" }));
assertThat(query.getQuery()).isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"LAST_NAME\" = :last_name OR (" + TABLE
+ ".\"LAST_NAME\" = :last_name OR (" + TABLE + ".\"FIRST_NAME\" = :first_name)"); + ".\"FIRST_NAME\" = :first_name)");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -166,8 +165,8 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { from, to }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { from, to });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE assertThat(query.getQuery())
+ ".\"DATE_OF_BIRTH\" BETWEEN :date_of_birth AND :date_of_birth1"); .isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" BETWEEN :date_of_birth AND :date_of_birth1");
assertThat(query.getParameterSource().getValue("date_of_birth")).isEqualTo(from); assertThat(query.getParameterSource().getValue("date_of_birth")).isEqualTo(from);
assertThat(query.getParameterSource().getValue("date_of_birth1")).isEqualTo(to); assertThat(query.getParameterSource().getValue("date_of_birth1")).isEqualTo(to);
@ -181,8 +180,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" < :age");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" < :age");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -193,8 +191,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" <= :age");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" <= :age");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -205,8 +202,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" > :age");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" > :age");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -217,8 +213,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 30 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" >= :age");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" >= :age");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -229,8 +224,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { new Date() }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { new Date() });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" > :date_of_birth");
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" > :date_of_birth");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -240,8 +234,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { new Date() }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { new Date() });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" < :date_of_birth");
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"DATE_OF_BIRTH\" < :date_of_birth");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -252,8 +245,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" IS NULL");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" IS NULL");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -264,8 +256,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" IS NOT NULL");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" IS NOT NULL");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -276,8 +267,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "%John%" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "%John%" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -288,8 +278,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "%John%" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "%John%" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -300,8 +289,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Jo" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Jo" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -312,8 +300,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Jo" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Jo" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("Jo%"); assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("Jo%");
} }
@ -325,8 +312,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "hn" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "hn" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -337,8 +323,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "hn" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "hn" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%hn"); assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%hn");
} }
@ -350,8 +335,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -362,8 +346,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%"); assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
} }
@ -375,8 +358,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -387,8 +369,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"FIRST_NAME\" NOT LIKE :first_name");
assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%"); assertThat(query.getParameterSource().getValue("first_name")).isEqualTo("%oh%");
} }
@ -400,8 +381,8 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 123 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 123 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery())
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" = :age ORDER BY \"LAST_NAME\" DESC"); .isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" = :age ORDER BY \"LAST_NAME\" DESC");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -411,8 +392,8 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 123 }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { 123 });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery())
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" = :age ORDER BY \"LAST_NAME\" ASC"); .isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" = :age ORDER BY \"LAST_NAME\" ASC");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -422,8 +403,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Doe" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Doe" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"LAST_NAME\" != :last_name");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"LAST_NAME\" != :last_name");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -435,8 +415,7 @@ public class PartTreeJdbcQueryUnitTests {
new Object[] { Collections.singleton(25) }); new Object[] { Collections.singleton(25) });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" IN (:age)");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" IN (:age)");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -447,8 +426,7 @@ public class PartTreeJdbcQueryUnitTests {
new Object[] { Collections.singleton(25) }); new Object[] { Collections.singleton(25) });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"AGE\" NOT IN (:age)");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"AGE\" NOT IN (:age)");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -459,8 +437,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = TRUE");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"ACTIVE\" = TRUE");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -471,8 +448,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[0]);
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()) assertThat(query.getQuery()).isEqualTo(BASE_SELECT + " WHERE " + TABLE + ".\"ACTIVE\" = FALSE");
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".\"ACTIVE\" = FALSE");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -483,8 +459,8 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
assertThat(query.getQuery()).isEqualTo( assertThat(query.getQuery())
"SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE UPPER(" + TABLE + ".\"FIRST_NAME\") = UPPER(:first_name)"); .isEqualTo(BASE_SELECT + " WHERE UPPER(" + TABLE + ".\"FIRST_NAME\") = UPPER(:first_name)");
} }
@Test // DATAJDBC-318 @Test // DATAJDBC-318
@ -525,8 +501,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE String expectedSql = BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" = :first_name LIMIT 3";
+ ".\"FIRST_NAME\" = :first_name LIMIT 3";
assertThat(query.getQuery()).isEqualTo(expectedSql); assertThat(query.getQuery()).isEqualTo(expectedSql);
} }
@ -538,8 +513,7 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "John" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE String expectedSql = BASE_SELECT + " WHERE " + TABLE + ".\"FIRST_NAME\" = :first_name LIMIT 1";
+ ".\"FIRST_NAME\" = :first_name LIMIT 1";
assertThat(query.getQuery()).isEqualTo(expectedSql); assertThat(query.getQuery()).isEqualTo(expectedSql);
} }
@ -552,8 +526,8 @@ public class PartTreeJdbcQueryUnitTests {
new Object[] { new Address("Hello", "World") }); new Object[] { new Address("Hello", "World") });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE (" + TABLE String expectedSql = BASE_SELECT + " WHERE (" + TABLE + ".\"USER_STREET\" = :user_street AND " + TABLE
+ ".\"USER_STREET\" = :user_street AND " + TABLE + ".\"USER_CITY\" = :user_city)"; + ".\"USER_CITY\" = :user_city)";
assertThat(query.getQuery()).isEqualTo(expectedSql); assertThat(query.getQuery()).isEqualTo(expectedSql);
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello"); assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
@ -568,16 +542,15 @@ public class PartTreeJdbcQueryUnitTests {
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Hello" }); RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Hello" });
ParametrizedQuery query = jdbcQuery.createQuery(accessor); ParametrizedQuery query = jdbcQuery.createQuery(accessor);
String expectedSql = "SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE String expectedSql = BASE_SELECT + " WHERE " + TABLE + ".\"USER_STREET\" = :user_street";
+ ".\"USER_STREET\" = :user_street";
assertThat(query.getQuery()).isEqualTo(expectedSql); assertThat(query.getQuery()).isEqualTo(expectedSql);
assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello"); assertThat(query.getParameterSource().getValue("user_street")).isEqualTo("Hello");
} }
private PartTreeJdbcQuery createQuery(JdbcQueryMethod queryMethod) { private PartTreeJdbcQuery createQuery(JdbcQueryMethod queryMethod) {
return new PartTreeJdbcQuery(queryMethod, H2Dialect.INSTANCE, converter, mock(NamedParameterJdbcOperations.class), return new PartTreeJdbcQuery(mappingContext, queryMethod, H2Dialect.INSTANCE, converter,
mock(RowMapper.class)); mock(NamedParameterJdbcOperations.class), mock(RowMapper.class));
} }
private JdbcQueryMethod getQueryMethod(String methodName, Class<?>... parameterTypes) throws Exception { private JdbcQueryMethod getQueryMethod(String methodName, Class<?>... parameterTypes) throws Exception {

3
spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/DefaultSelectBuilder.java

@ -288,7 +288,6 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn
private @Nullable Expression to; private @Nullable Expression to;
private @Nullable Condition condition; private @Nullable Condition condition;
JoinBuilder(Table table, DefaultSelectBuilder selectBuilder, JoinType joinType) { JoinBuilder(Table table, DefaultSelectBuilder selectBuilder, JoinType joinType) {
this.table = table; this.table = table;
@ -341,10 +340,10 @@ class DefaultSelectBuilder implements SelectBuilder, SelectAndFrom, SelectFromAn
} else { } else {
condition = condition.and(comparison); condition = condition.and(comparison);
} }
} }
private Join finishJoin() { private Join finishJoin() {
finishCondition(); finishCondition();
return new Join(joinType, table, condition); return new Join(joinType, table, condition);
} }

Loading…
Cancel
Save