Skip to content

Commit ad31b14

Browse files
committed
works somehow
1 parent 36fd1ba commit ad31b14

File tree

5 files changed

+124
-134
lines changed

5 files changed

+124
-134
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/SqlGenerator.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ public class SqlGenerator {
113113
this.dialect = dialect;
114114
}
115115

116+
117+
public SelectBuilder.SelectWhere createSelectBuilder(Table table, Predicate<AggregatePath> pathFilter) {
118+
return createSelectBuilder(table, pathFilter, Collections.emptyList());
119+
}
120+
116121
/**
117122
* When deleting entities there is a fundamental difference between deleting
118123
* <ol>
@@ -573,15 +578,11 @@ private SelectBuilder.SelectWhere selectBuilder() {
573578

574579
private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyColumns) {
575580

576-
return createSelectBuilder(keyColumns, ap -> false, getTable());
577-
}
578-
579-
public SelectBuilder.SelectWhere createSelectBuilder(Predicate<AggregatePath> pathFilter, Table table) {
580-
return createSelectBuilder(Collections.emptyList(), pathFilter, table);
581+
return createSelectBuilder(getTable(), ap -> false, keyColumns);
581582
}
582583

583-
private SelectBuilder.SelectWhere createSelectBuilder(Collection<SqlIdentifier> keyColumns,
584-
Predicate<AggregatePath> pathFilter, Table table) {
584+
private SelectBuilder.SelectWhere createSelectBuilder(Table table, Predicate<AggregatePath> pathFilter,
585+
Collection<SqlIdentifier> keyColumns) {
585586

586587
Set<Expression> columnExpressions = new LinkedHashSet<>();
587588

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

Lines changed: 10 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.jdbc.repository.query;
1717

18-
import java.util.ArrayList;
19-
import java.util.List;
2018
import java.util.Optional;
2119
import java.util.function.Predicate;
2220

@@ -81,14 +79,16 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
8179
* @param accessor parameter metadata provider, must not be {@literal null}.
8280
* @param isSliceQuery flag denoting if the query returns a {@link org.springframework.data.domain.Slice}.
8381
* @param returnedType the {@link ReturnedType} to be returned by the query. Must not be {@literal null}.
84-
*
85-
* @deprecated use {@link JdbcQueryCreator#JdbcQueryCreator(RelationalMappingContext, PartTree, JdbcConverter, Dialect, RelationalEntityMetadata, RelationalParameterAccessor, boolean, ReturnedType, Optional, SqlGeneratorSource)} instead.
82+
* @deprecated use
83+
* {@link JdbcQueryCreator#JdbcQueryCreator(RelationalMappingContext, PartTree, JdbcConverter, Dialect, RelationalEntityMetadata, RelationalParameterAccessor, boolean, ReturnedType, Optional, SqlGeneratorSource)}
84+
* instead.
8685
*/
8786
@Deprecated(since = "4.0", forRemoval = true)
8887
JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
8988
RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor, boolean isSliceQuery,
9089
ReturnedType returnedType, Optional<Lock> lockMode) {
91-
this(context, tree, converter, dialect, entityMetadata, accessor, isSliceQuery, returnedType, lockMode, new SqlGeneratorSource(context, converter, dialect));
90+
this(context, tree, converter, dialect, entityMetadata, accessor, isSliceQuery, returnedType, lockMode,
91+
new SqlGeneratorSource(context, converter, dialect));
9292
}
9393

9494
/**
@@ -104,8 +104,8 @@ class JdbcQueryCreator extends RelationalQueryCreator<ParametrizedQuery> {
104104
* @param isSliceQuery flag denoting if the query returns a {@link org.springframework.data.domain.Slice}.
105105
* @param returnedType the {@link ReturnedType} to be returned by the query. Must not be {@literal null}.
106106
* @param lockMode lock mode to be used for the query.
107-
* @param sqlGeneratorSource the source providing SqlGenerator instances for generating SQL. Must not be {@literal null}
108-
*
107+
* @param sqlGeneratorSource the source providing SqlGenerator instances for generating SQL. Must not be
108+
* {@literal null}
109109
*/
110110
JdbcQueryCreator(RelationalMappingContext context, PartTree tree, JdbcConverter converter, Dialect dialect,
111111
RelationalEntityMetadata<?> entityMetadata, RelationalParameterAccessor accessor, boolean isSliceQuery,
@@ -258,125 +258,13 @@ SelectBuilder.SelectLimitOffset createSelectClause(RelationalPersistentEntity<?>
258258

259259
private SelectBuilder.SelectJoin selectBuilder(Table table) {
260260

261-
262-
List<Expression> columnExpressions = new ArrayList<>();
263261
RelationalPersistentEntity<?> entity = entityMetadata.getTableEntity();
264262

265-
Predicate<AggregatePath> filter = ap -> returnedType.needsCustomConstruction() && !returnedType.getInputProperties().contains(ap.getRequiredBaseProperty().getName());
266-
267-
return (SelectBuilder.SelectJoin) sqlGeneratorSource.getSqlGenerator(entity.getType()).createSelectBuilder(
268-
filter
269-
, table);
270-
//
271-
// SqlContext sqlContext = new SqlContext();
272-
//
273-
// List<Join> joinTables = new ArrayList<>();
274-
// for (PersistentPropertyPath<RelationalPersistentProperty> path : context
275-
// .findPersistentPropertyPaths(entity.getType(), p -> true)) {
276-
//
277-
// AggregatePath aggregatePath = context.getAggregatePath(path);
278-
//
279-
// if (filter.test(aggregatePath)) { continue;}
280-
//
281-
// // add a join if necessary
282-
// Join join = getJoin(sqlContext, aggregatePath);
283-
// if (join != null) {
284-
// joinTables.add(join);
285-
// }
286-
//
287-
// Column column = getColumn(sqlContext, aggregatePath);
288-
// if (column != null) {
289-
// columnExpressions.add(column);
290-
// }
291-
// }
292-
//
293-
// SelectBuilder.SelectJoin baseSelect = StatementBuilder.select(columnExpressions).from(table);
294-
//
295-
// // TODO: included in SqlGenerator.Join
296-
// for (Join join : joinTables) {
297-
//
298-
// Condition condition = null;
299-
//
300-
// for (int i = 0; i < join.joinColumns.size(); i++) {
301-
// Column parentColumn = join.parentId.get(i);
302-
// Column joinColumn = join.joinColumns.get(i);
303-
// Comparison singleCondition = joinColumn.isEqualTo(parentColumn);
304-
// condition = condition == null ? singleCondition : condition.and(singleCondition);
305-
// }
306-
//
307-
// Assert.state(condition != null, "No condition found");
308-
//
309-
// baseSelect = baseSelect.leftOuterJoin(join.joinTable).on(condition);
310-
// }
311-
//
312-
// return baseSelect;
313-
}
314-
315-
/**
316-
* Create a {@link Column} for {@link AggregatePath}.
317-
*
318-
* @param sqlContext for generating SQL constructs.
319-
* @param path the path to the column in question.
320-
* @return the statement as a {@link String}. Guaranteed to be not {@literal null}.
321-
*/
322-
@Nullable
323-
private Column getColumn(SqlContext sqlContext, AggregatePath path) {
324-
325-
// an embedded itself doesn't give an column, its members will though.
326-
// 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
327-
// select
328-
// only the parent path is considered in order to handle arrays that get stored as BINARY properly
329-
if (path.isEmbedded() || path.getParentPath().isMultiValued()) {
330-
return null;
331-
}
332-
333-
if (path.isEntity()) {
334-
335-
if (path.isQualified() //
336-
|| path.isCollectionLike() //
337-
|| path.hasIdProperty() //
338-
) {
339-
return null;
340-
}
341-
342-
// Simple entities without id include there backreference as an synthetic id in order to distinguish null entities
343-
// from entities with only null values.
344-
return sqlContext.getAnyReverseColumn(path);
345-
}
263+
Predicate<AggregatePath> filter = ap -> returnedType.needsCustomConstruction()
264+
&& !returnedType.getInputProperties().contains(ap.getRequiredBaseProperty().getName());
346265

347-
return sqlContext.getColumn(path);
348-
}
349-
350-
@Nullable
351-
Join getJoin(SqlContext sqlContext, AggregatePath path) {
352-
353-
if (!path.isEntity() || path.isEmbedded() || path.isMultiValued()) {
354-
return null;
355-
}
356-
357-
Table currentTable = sqlContext.getTable(path);
358-
359-
AggregatePath idDefiningParentPath = path.getIdDefiningParentPath();
360-
Table parentTable = sqlContext.getTable(idDefiningParentPath);
361-
362-
List<Column> reverseColumns = path.getTableInfo().backReferenceColumnInfos().toColumnList(currentTable);
363-
List<Column> idColumns = idDefiningParentPath.getTableInfo().idColumnInfos().toColumnList(parentTable);
364-
return new Join( //
365-
currentTable, //
366-
reverseColumns, //
367-
idColumns //
266+
return (SelectBuilder.SelectJoin) sqlGeneratorSource.getSqlGenerator(entity.getType()).createSelectBuilder(table, filter
368267
);
369268
}
370269

371-
/**
372-
* Value object representing a {@code JOIN} association.
373-
*/
374-
private record Join(Table joinTable, List<Column> joinColumns, List<Column> parentId) {
375-
376-
Join {
377-
Assert.isTrue(joinColumns.size() == parentId.size(),
378-
"Both sides of a join condition must have the same number of columns");
379-
}
380-
381-
}
382270
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.mapping;
17+
18+
import org.assertj.core.api.AbstractAssert;
19+
20+
public class AggregatePathAssertions extends AbstractAssert<AggregatePathAssertions, AggregatePath> {
21+
22+
// Constructor for initializing with an AggregatePath instance
23+
public AggregatePathAssertions(AggregatePath actual) {
24+
super(actual, AggregatePathAssertions.class);
25+
}
26+
27+
/**
28+
* Entry point for creating assertions for AggregatePath.
29+
*/
30+
public static AggregatePathAssertions assertThat(AggregatePath actual) {
31+
return new AggregatePathAssertions(actual);
32+
}
33+
34+
/**
35+
* Example custom assertion method: Asserts that the AggregatePath has a specific property.
36+
*/
37+
public AggregatePathAssertions hasPath(String expectedPath) {
38+
isNotNull();
39+
40+
if (!actual.toString().equals(expectedPath)) { // Adjust this condition based on your AggregatePath's path logic
41+
failWithMessage("Expected path to be <%s> but was <%s>", expectedPath, actual.toString());
42+
}
43+
return this;
44+
}
45+
46+
/**
47+
* Example custom assertion method: Checks if the AggregatePath is empty.
48+
*/
49+
public AggregatePathAssertions isRoot() {
50+
isNotNull();
51+
52+
if (!actual.isRoot()) {
53+
failWithMessage("Expected AggregatePath to be root path, but it was not");
54+
}
55+
return this;
56+
}
57+
58+
/**
59+
* Example custom assertion method: Validates the depth of the path.
60+
*/
61+
public AggregatePathAssertions hasLength(int expectedLength) {
62+
isNotNull();
63+
64+
if (actual.getLength() != expectedLength) {
65+
failWithMessage("Expected path length to be <%d> but was <%d>", expectedLength, actual.getLength());
66+
}
67+
return this;
68+
}
69+
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.mapping;
17+
18+
import org.assertj.core.api.SoftAssertions;
19+
import org.assertj.core.api.SoftAssertionsProvider;
20+
21+
import java.util.function.Consumer;
22+
23+
public class AggregatePathSoftAssertions extends SoftAssertions {
24+
public AggregatePathAssertions assertAggregatePath(AggregatePath actual) {
25+
return proxy(AggregatePathAssertions.class, AggregatePath.class, actual);
26+
}
27+
28+
static void assertNewSoftly(Consumer<AggregatePathSoftAssertions> softly) {
29+
SoftAssertionsProvider.assertSoftly(AggregatePathSoftAssertions.class, softly);
30+
}
31+
}

spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DefaultAggregatePathUnitTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ void isRootForRootPath() {
6464
@Test // GH-1525
6565
void getParentPath() {
6666

67-
assertSoftly(softly -> {
67+
AggregatePathSoftAssertions.assertNewSoftly(softly -> {
6868

69-
softly.assertThat((Object) path("second.third2.value").getParentPath()).isEqualTo(path("second.third2"));
70-
softly.assertThat((Object) path("second.third2").getParentPath()).isEqualTo(path("second"));
71-
softly.assertThat((Object) path("second").getParentPath()).isEqualTo(path());
69+
softly.assertAggregatePath(path("second.third2.value").getParentPath()).hasPath("second.third2");
70+
softly.assertAggregatePath(path("second.third2").getParentPath()).hasPath("second");
71+
softly.assertAggregatePath(path("second").getParentPath()).isRoot();
7272

7373
softly.assertThatThrownBy(() -> path().getParentPath()).isInstanceOf(IllegalStateException.class);
7474
});
@@ -489,7 +489,7 @@ void getTail() {
489489
void append() {
490490

491491
assertSoftly(softly -> {
492-
492+
// assert that( .... ) matches ("second")
493493
softly.assertThat(path("second").append(path()).toDotPath()).isEqualTo("second");
494494
softly.assertThat(path().append(path("second")).toDotPath()).isEqualTo("second");
495495
softly.assertThat(path().append(path("second.third")).toDotPath()).isEqualTo("second.third");

0 commit comments

Comments
 (0)