Polishing.

Simplify ValueFunction mapping. Remove invariants of findBy SQL generation in favor of the Condition-based variant. Reduce visibility. Change return value of AggregateReader to List

See #1601
Original pull request: #1617
This commit is contained in:
Jens Schauder
2023-09-25 10:09:37 +02:00
committed by Mark Paluch
parent 0fdeaebbee
commit f3bc0af8c4
15 changed files with 120 additions and 227 deletions

View File

@@ -18,16 +18,16 @@ package org.springframework.data.jdbc.core.convert;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.mapping.AggregatePath;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.CriteriaDefinition;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.sql.Condition;
@@ -36,6 +36,7 @@ import org.springframework.data.relational.core.sqlgeneration.AliasFactory;
import org.springframework.data.relational.core.sqlgeneration.SingleQuerySqlGenerator;
import org.springframework.data.relational.core.sqlgeneration.SqlGenerator;
import org.springframework.data.relational.domain.RowDocument;
import org.springframework.data.util.Streamable;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.lang.Nullable;
@@ -43,7 +44,7 @@ import org.springframework.util.Assert;
/**
* Reads complete Aggregates from the database, by generating appropriate SQL using a {@link SingleQuerySqlGenerator}
* through {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}. Results are converterd into an
* through {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}. Results are converted into an
* intermediate {@link RowDocumentResultSetExtractor RowDocument} and mapped via
* {@link org.springframework.data.relational.core.conversion.RelationalConverter#read(Class, RowDocument)}.
*
@@ -55,7 +56,8 @@ import org.springframework.util.Assert;
class AggregateReader<T> {
private final RelationalPersistentEntity<T> aggregate;
private final org.springframework.data.relational.core.sqlgeneration.SqlGenerator sqlGenerator;
private final Table table;
private final SqlGenerator sqlGenerator;
private final JdbcConverter converter;
private final NamedParameterJdbcOperations jdbcTemplate;
private final RowDocumentResultSetExtractor extractor;
@@ -66,6 +68,7 @@ class AggregateReader<T> {
this.converter = converter;
this.aggregate = aggregate;
this.jdbcTemplate = jdbcTemplate;
this.table = Table.create(aggregate.getQualifiedTableName());
this.sqlGenerator = new CachingSqlGenerator(
new SingleQuerySqlGenerator(converter.getMappingContext(), aliasFactory, dialect, aggregate));
@@ -74,62 +77,58 @@ class AggregateReader<T> {
createPathToColumnMapping(aliasFactory));
}
@Nullable
public T findById(Object id) {
Query query = Query.query(Criteria.where(aggregate.getRequiredIdProperty().getName()).is(id)).limit(1);
return findOne(query);
}
@Nullable
public T findOne(Query query) {
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
Condition condition = createCondition(query, parameterSource);
return jdbcTemplate.query(sqlGenerator.findAll(condition), parameterSource, this::extractZeroOrOne);
}
public List<T> findAll() {
return jdbcTemplate.query(sqlGenerator.findAll(), this::extractAll);
}
public List<T> findAllById(Iterable<?> ids) {
Collection<?> identifiers = ids instanceof Collection<?> idl ? idl : Streamable.of(ids).toList();
Query query = Query.query(Criteria.where(aggregate.getRequiredIdProperty().getName()).in(identifiers)).limit(1);
return findAll(query);
}
public List<T> findAll(Query query) {
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
Condition condition = createCondition(query, parameterSource);
return jdbcTemplate.query(sqlGenerator.findAll(condition), parameterSource, this::extractAll);
}
@Nullable
public T findById(Object id) {
id = converter.writeValue(id, aggregate.getRequiredIdProperty().getTypeInformation());
return jdbcTemplate.query(sqlGenerator.findById(), Map.of("id", id), this::extractZeroOrOne);
}
public Iterable<T> findAllById(Iterable<?> ids) {
List<Object> convertedIds = new ArrayList<>();
for (Object id : ids) {
convertedIds.add(converter.writeValue(id, aggregate.getRequiredIdProperty().getTypeInformation()));
}
return jdbcTemplate.query(sqlGenerator.findAllById(), Map.of("ids", convertedIds), this::extractAll);
}
public Iterable<T> findAllBy(Query query) {
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
BiFunction<Table, RelationalPersistentEntity, Condition> condition = createConditionSource(query, parameterSource);
return jdbcTemplate.query(sqlGenerator.findAllByCondition(condition), parameterSource, this::extractAll);
}
public Optional<T> findOneByQuery(Query query) {
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
BiFunction<Table, RelationalPersistentEntity, Condition> condition = createConditionSource(query, parameterSource);
return Optional.ofNullable(
jdbcTemplate.query(sqlGenerator.findAllByCondition(condition), parameterSource, this::extractZeroOrOne));
}
private BiFunction<Table, RelationalPersistentEntity, Condition> createConditionSource(Query query, MapSqlParameterSource parameterSource) {
private Condition createCondition(Query query, MapSqlParameterSource parameterSource) {
QueryMapper queryMapper = new QueryMapper(converter);
BiFunction<Table, RelationalPersistentEntity, Condition> condition = (table, aggregate) -> {
Optional<CriteriaDefinition> criteria = query.getCriteria();
return criteria
.map(criteriaDefinition -> queryMapper.getMappedObject(parameterSource, criteriaDefinition, table, aggregate))
.orElse(null);
};
return condition;
Optional<CriteriaDefinition> criteria = query.getCriteria();
return criteria
.map(criteriaDefinition -> queryMapper.getMappedObject(parameterSource, criteriaDefinition, table, aggregate))
.orElse(null);
}
/**
* Extracts a list of aggregates from the given {@link ResultSet} by utilizing the
* {@link RowDocumentResultSetExtractor} and the {@link JdbcConverter}. When used as a method reference this conforms
* to the {@link org.springframework.jdbc.core.ResultSetExtractor} contract.
*
*
* @param rs the {@link ResultSet} from which to extract the data. Must not be {(}@literal null}.
* @return a {@code List} of aggregates, fully converted.
* @throws SQLException
@@ -195,21 +194,15 @@ class AggregateReader<T> {
* @author Jens Schauder
* @since 3.2
*/
static class CachingSqlGenerator implements org.springframework.data.relational.core.sqlgeneration.SqlGenerator {
private final org.springframework.data.relational.core.sqlgeneration.SqlGenerator delegate;
static class CachingSqlGenerator implements SqlGenerator {
private final SqlGenerator delegate;
private final String findAll;
private final String findById;
private final String findAllById;
public CachingSqlGenerator(SqlGenerator delegate) {
this.delegate = delegate;
findAll = delegate.findAll();
findById = delegate.findById();
findAllById = delegate.findAllById();
this.findAll = delegate.findAll();
}
@Override
@@ -218,18 +211,8 @@ class AggregateReader<T> {
}
@Override
public String findById() {
return findById;
}
@Override
public String findAllById() {
return findAllById;
}
@Override
public String findAllByCondition(BiFunction<Table, RelationalPersistentEntity, Condition> conditionSource) {
return delegate.findAllByCondition(conditionSource);
public String findAll(@Nullable Condition condition) {
return delegate.findAll(condition);
}
@Override

View File

@@ -22,8 +22,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
@@ -35,7 +33,6 @@ import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.query.CriteriaDefinition;
@@ -77,7 +74,7 @@ public class QueryMapper {
Assert.notNull(converter, "JdbcConverter must not be null");
this.converter = converter;
this.mappingContext = (MappingContext) converter.getMappingContext();
this.mappingContext = converter.getMappingContext();
}
/**
@@ -310,7 +307,7 @@ public class QueryMapper {
sqlType = getTypeHint(mappedValue, actualType.getType(), settableValue);
} else if (criteria.getValue() instanceof ValueFunction valueFunction) {
mappedValue = valueFunction.transform(v -> convertValue(comparator, v, propertyField.getTypeHint()));
mappedValue = valueFunction.map(v -> convertValue(comparator, v, propertyField.getTypeHint()));
sqlType = propertyField.getSqlType();
} else if (propertyField instanceof MetadataBackedField metadataBackedField //

View File

@@ -77,13 +77,12 @@ class SingleQueryDataAccessStrategy implements ReadingDataAccessStrategy {
@Override
public <T> Optional<T> findOne(Query query, Class<T> domainType) {
return getReader(domainType).findOneByQuery(query);
return Optional.ofNullable(getReader(domainType).findOne(query));
}
@Override
public <T> Iterable<T> findAll(Query query, Class<T> domainType) {
return getReader(domainType).findAllBy(query);
return getReader(domainType).findAll(query);
}
@Override

View File

@@ -87,6 +87,7 @@ class SingleQueryFallbackDataAccessStrategy extends DelegatingDataAccessStrategy
return super.findAllById(ids, domainType);
}
@Override
public <T> Optional<T> findOne(Query query, Class<T> domainType) {
if (isSingleSelectQuerySupported(domainType) && isSingleSelectQuerySupported(query)) {
@@ -137,11 +138,6 @@ class SingleQueryFallbackDataAccessStrategy extends DelegatingDataAccessStrategy
referenceFound = true;
}
// AggregateReferences aren't supported yet
// if (property.isAssociation()) {
// return false;
// }
}
return true;

View File

@@ -21,12 +21,13 @@ import org.springframework.data.relational.core.query.ValueFunction;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* This {@link SqlParameterSource} will apply escaping to it's values.
*
* This {@link SqlParameterSource} will apply escaping to its values.
*
* @author Jens Schauder
* @since 3.2
*/
public class EscapingParameterSource implements SqlParameterSource {
class EscapingParameterSource implements SqlParameterSource {
private final SqlParameterSource parameterSource;
private final Escaper escaper;

View File

@@ -15,12 +15,12 @@
*/
package org.springframework.data.jdbc.repository.query;
import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
/**
* Value object encapsulating a query containing named parameters and a{@link SqlParameterSource} to bind the parameters.
* Value object encapsulating a query containing named parameters and a{@link SqlParameterSource} to bind the
* parameters.
*
* @author Mark Paluch
* @author Jens Schauder
@@ -41,13 +41,12 @@ class ParametrizedQuery {
return query;
}
SqlParameterSource getParameterSource(Escaper escaper) {
return new EscapingParameterSource(parameterSource, escaper);
}
@Override
public String toString() {
return this.query;
}
public SqlParameterSource getParameterSource(Escaper escaper) {
return new EscapingParameterSource(parameterSource, escaper);
}
}

View File

@@ -176,9 +176,8 @@ public class QueryMapper {
return expression;
}
if (expression instanceof Column) {
if (expression instanceof Column column) {
Column column = (Column) expression;
Field field = createPropertyField(entity, column.getName());
TableLike table = column.getTable();
@@ -186,9 +185,7 @@ public class QueryMapper {
return column instanceof Aliased ? columnFromTable.as(((Aliased) column).getAlias()) : columnFromTable;
}
if (expression instanceof SimpleFunction) {
SimpleFunction function = (SimpleFunction) expression;
if (expression instanceof SimpleFunction function) {
List<Expression> arguments = function.getExpressions();
List<Expression> mappedArguments = new ArrayList<>(arguments.size());
@@ -367,15 +364,14 @@ public class QueryMapper {
Class<?> typeHint;
Comparator comparator = criteria.getComparator();
if (criteria.getValue() instanceof Parameter) {
Parameter parameter = (Parameter) criteria.getValue();
if (criteria.getValue()instanceof Parameter parameter) {
mappedValue = convertValue(comparator, parameter.getValue(), propertyField.getTypeHint());
typeHint = getTypeHint(mappedValue, actualType.getType(), parameter);
} else if (criteria.getValue() instanceof ValueFunction<?> valueFunction) {
mappedValue = valueFunction.transform(v -> convertValue(comparator, v, propertyField.getTypeHint())).apply(getEscaper(comparator));
mappedValue = valueFunction.map(v -> convertValue(comparator, v, propertyField.getTypeHint()))
.apply(getEscaper(comparator));
typeHint = actualType.getType();
} else {

View File

@@ -118,7 +118,7 @@ public class UpdateMapper extends QueryMapper {
} else if (value instanceof ValueFunction<?> valueFunction) {
mappedValue = valueFunction.transform(v -> convertValue(v, propertyField.getTypeHint())).apply(Escaper.DEFAULT);
mappedValue = valueFunction.map(v -> convertValue(v, propertyField.getTypeHint())).apply(Escaper.DEFAULT);
if (mappedValue == null) {
return Assignments.value(column, SQL.nullLiteral());

View File

@@ -58,14 +58,18 @@ public interface ValueFunction<T> extends Function<Escaper, T> {
}
/**
* Transforms the inner value of the ValueFunction using the profided transformation.
* Return a new ValueFunction applying the given mapping {@link Function}. The mapping function is applied after
* applying {@link Escaper}.
*
* The default implementation just return the current {@literal ValueFunction}.
* This is not a valid implementation and serves just to maintain backward compatibility.
*
* @param transformation to be applied to the underlying value.
* @param mapper the mapping function to apply to the value.
* @param <R> the type of the value returned from the mapping function.
* @return a new {@literal ValueFunction}.
* @since 3.2
*/
default ValueFunction<T> transform(Function<Object, Object> transformation) {return this;};
default <R> ValueFunction<R> map(Function<T, R> mapper) {
Assert.notNull(mapper, "Mapping function must not be null");
return escaper -> mapper.apply(this.apply(escaper));
}
}

View File

@@ -19,9 +19,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
@@ -46,7 +46,6 @@ public class SingleQuerySqlGenerator implements SqlGenerator {
private final Dialect dialect;
private final AliasFactory aliases;
private final RelationalPersistentEntity<?> aggregate;
private final Table table;
public SingleQuerySqlGenerator(RelationalMappingContext context, AliasFactory aliasFactory, Dialect dialect,
RelationalPersistentEntity<?> aggregate) {
@@ -55,47 +54,14 @@ public class SingleQuerySqlGenerator implements SqlGenerator {
this.aliases = aliasFactory;
this.dialect = dialect;
this.aggregate = aggregate;
this.table = Table.create(aggregate.getQualifiedTableName());
}
@Override
public String findAll() {
return createSelect(null);
}
@Override
public String findById() {
AggregatePath path = getRootIdPath();
Condition condition = Conditions.isEqual(table.column(path.getColumnInfo().name()), Expressions.just(":id"));
public String findAll(@Nullable Condition condition) {
return createSelect(condition);
}
@Override
public String findAllById() {
AggregatePath path = getRootIdPath();
Condition condition = Conditions.in(table.column(path.getColumnInfo().name()), Expressions.just(":ids"));
return createSelect(condition);
}
@Override
public String findAllByCondition(BiFunction<Table, RelationalPersistentEntity, Condition> conditionSource) {
Condition condition = conditionSource.apply(table, aggregate);
return createSelect(condition);
}
/**
* @return The {@link AggregatePath} to the id property of the aggregate root.
*/
private AggregatePath getRootIdPath() {
return context.getAggregatePath(aggregate).append(aggregate.getRequiredIdProperty());
}
String createSelect(Condition condition) {
String createSelect(@Nullable Condition condition) {
AggregatePath rootPath = context.getAggregatePath(aggregate);
QueryMeta queryMeta = createInlineQuery(rootPath, condition);
@@ -168,7 +134,7 @@ public class SingleQuerySqlGenerator implements SqlGenerator {
List<QueryMeta> inlineQueries = new ArrayList<>();
for (PersistentPropertyPath ppp : paths) {
for (PersistentPropertyPath<? extends RelationalPersistentProperty> ppp : paths) {
QueryMeta queryMeta = createInlineQuery(context.getAggregatePath(ppp), null);
inlineQueries.add(queryMeta);
@@ -188,7 +154,7 @@ public class SingleQuerySqlGenerator implements SqlGenerator {
* @param condition a condition that is to be applied to the query. May be {@literal null}.
* @return an inline query for the given path.
*/
private QueryMeta createInlineQuery(AggregatePath basePath, Condition condition) {
private QueryMeta createInlineQuery(AggregatePath basePath, @Nullable Condition condition) {
RelationalPersistentEntity<?> entity = basePath.getRequiredLeafEntity();
Table table = Table.create(entity.getQualifiedTableName());

View File

@@ -15,11 +15,8 @@
*/
package org.springframework.data.relational.core.sqlgeneration;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.sql.Condition;
import org.springframework.data.relational.core.sql.Table;
import java.util.function.BiFunction;
import org.springframework.lang.Nullable;
/**
* Generates SQL statements for loading aggregates.
@@ -28,13 +25,12 @@ import java.util.function.BiFunction;
* @since 3.2
*/
public interface SqlGenerator {
String findAll();
String findById();
default String findAll() {
return findAll(null);
}
String findAllById();
String findAllByCondition(BiFunction<Table, RelationalPersistentEntity, Condition> conditionSource);
String findAll(@Nullable Condition condition);
AliasFactory getAliasFactory();
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.repository.query;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.data.relational.core.query.ValueFunction;
import java.util.function.Function;
/**
* Value function that has an underlying value and a modifier that gets applied after the escaper.
*
* @author Jens Schauder
* @since 3.2
*/
record ModifyingValueFunction(Object value, Function<String, String> modifier) implements ValueFunction<String> {
static ModifyingValueFunction of(Object value, Function<String, String> modifier) {
return new ModifyingValueFunction(value, modifier);
}
@Override
public String apply(Escaper escaper) {
return modifier.apply(escaper.escape(value.toString()));
}
@Override
public ValueFunction<String> transform(Function<Object, Object> transformation) {
return new ModifyingValueFunction(transformation.apply(value), modifier);
}
}

View File

@@ -20,6 +20,7 @@ import java.util.Iterator;
import java.util.List;
import org.springframework.data.relational.core.dialect.Escaper;
import org.springframework.data.relational.core.query.ValueFunction;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.parser.Part;
@@ -136,16 +137,12 @@ class ParameterMetadataProvider implements Iterable<ParameterMetadata> {
return value;
}
switch (partType) {
case STARTING_WITH:
return ModifyingValueFunction.of(value, s -> s + "%");
case ENDING_WITH:
return ModifyingValueFunction.of(value, s -> "%" + s);
case CONTAINING:
case NOT_CONTAINING:
return ModifyingValueFunction.of(value, s -> "%" + s + "%");
default:
return value;
}
return switch (partType) {
case STARTING_WITH -> (ValueFunction<String>) escaper -> escaper.escape(value.toString()) + "%";
case ENDING_WITH -> (ValueFunction<String>) escaper -> "%" + escaper.escape(value.toString());
case CONTAINING, NOT_CONTAINING -> (ValueFunction<String>) escaper -> "%" + escaper.escape(value.toString())
+ "%";
default -> value;
};
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.data.relational.core.mapping;
import static org.assertj.core.api.Assertions.*;
import static org.assertj.core.api.SoftAssertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
@@ -44,7 +43,6 @@ public class DerivedSqlIdentifierUnitTests {
assertThat(identifier.toSql(BRACKETS_LOWER_CASE)).isEqualTo("[somename]");
assertThat(identifier.getReference(BRACKETS_LOWER_CASE)).isEqualTo("someName");
assertThat(identifier.getReference()).isEqualTo("someName");
}
@Test // DATAJDBC-386
@@ -77,12 +75,12 @@ public class DerivedSqlIdentifierUnitTests {
SqlIdentifier notSimple = SqlIdentifier.from(new DerivedSqlIdentifier("simple", false),
new DerivedSqlIdentifier("not", false));
assertSoftly(softly -> {
assertThat(basis).isEqualTo(equal).isEqualTo(SqlIdentifier.unquoted("simple"))
.hasSameHashCodeAs(SqlIdentifier.unquoted("simple"));
assertThat(equal).isEqualTo(basis);
assertThat(basis).isNotEqualTo(quoted);
assertThat(basis).isNotEqualTo(notSimple);
softly.assertThat(basis).isEqualTo(equal);
softly.assertThat(equal).isEqualTo(basis);
softly.assertThat(basis).isNotEqualTo(quoted);
softly.assertThat(basis).isNotEqualTo(notSimple);
});
assertThat(quoted).isEqualTo(SqlIdentifier.quoted("SIMPLE")).hasSameHashCodeAs(SqlIdentifier.quoted("SIMPLE"));
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.relational.core.sqlgeneration;
import static org.springframework.data.relational.core.sqlgeneration.SqlAssert.*;
@@ -28,7 +27,10 @@ import org.springframework.data.relational.core.dialect.Dialect;
import org.springframework.data.relational.core.dialect.PostgresDialect;
import org.springframework.data.relational.core.mapping.AggregatePath;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.Conditions;
import org.springframework.data.relational.core.sql.Table;
/**
* Tests for {@link SingleQuerySqlGenerator}.
@@ -76,7 +78,8 @@ class SingleQuerySqlGeneratorUnitTests {
@Test // GH-1446
void createSelectForFindById() {
String sql = sqlGenerator.findById();
Table table = Table.create(persistentEntity.getQualifiedTableName());
String sql = sqlGenerator.findAll(table.column("id").isEqualTo(Conditions.just(":id")));
SqlAssert baseSelect = assertThatParsed(sql).hasInlineView();
@@ -94,13 +97,14 @@ class SingleQuerySqlGeneratorUnitTests {
col("\"id\"").as(alias("id")), //
col("\"name\"").as(alias("name")) //
) //
.extractWhereClause().isEqualTo("\"trivial_aggregate\".\"id\" = :id");
.extractWhereClause().isEqualTo("\"trivial_aggregate\".id = :id");
}
@Test // GH-1446
void createSelectForFindAllById() {
String sql = sqlGenerator.findAllById();
Table table = Table.create(persistentEntity.getQualifiedTableName());
String sql = sqlGenerator.findAll(table.column("id").in(Conditions.just(":ids")));
SqlAssert baseSelect = assertThatParsed(sql).hasInlineView();
@@ -118,7 +122,7 @@ class SingleQuerySqlGeneratorUnitTests {
col("\"id\"").as(alias("id")), //
col("\"name\"").as(alias("name")) //
) //
.extractWhereClause().isEqualTo("\"trivial_aggregate\".\"id\" IN (:ids)");
.extractWhereClause().isEqualTo("\"trivial_aggregate\".id IN (:ids)");
}
}
@@ -133,7 +137,8 @@ class SingleQuerySqlGeneratorUnitTests {
@Test // GH-1446
void createSelectForFindById() {
String sql = sqlGenerator.findById();
Table table = Table.create(persistentEntity.getQualifiedTableName());
String sql = sqlGenerator.findAll(table.column("id").isEqualTo(Conditions.just(":id")));
String rootRowNumber = rnAlias();
String rootCount = rcAlias();
@@ -167,7 +172,7 @@ class SingleQuerySqlGeneratorUnitTests {
col("\"id\"").as(alias("id")), //
col("\"name\"").as(alias("name")) //
) //
.extractWhereClause().isEqualTo("\"single_reference_aggregate\".\"id\" = :id");
.extractWhereClause().isEqualTo("\"single_reference_aggregate\".id = :id");
baseSelect.hasInlineViewSelectingFrom("\"trivial_aggregate\"") //
.hasExactlyColumns( //
rn(col("\"single_reference_aggregate\"")).as(trivialsRowNumber), //
@@ -206,13 +211,14 @@ class SingleQuerySqlGeneratorUnitTests {
private class AbstractTestFixture {
final Class<?> aggregateRootType;
final SingleQuerySqlGenerator sqlGenerator;
final RelationalPersistentEntity<?> persistentEntity;
final AliasFactory aliases;
private AbstractTestFixture(Class<?> aggregateRootType) {
this.aggregateRootType = aggregateRootType;
this.sqlGenerator = new SingleQuerySqlGenerator(context, new AliasFactory(), dialect,
context.getRequiredPersistentEntity(aggregateRootType));
this.persistentEntity = context.getRequiredPersistentEntity(aggregateRootType);
this.sqlGenerator = new SingleQuerySqlGenerator(context, new AliasFactory(), dialect, persistentEntity);
this.aliases = sqlGenerator.getAliasFactory();
}