Skip to content

Commit 2bc4cc6

Browse files
committed
Avoid selection of duplicate columns.
Closes #1865
1 parent b6d3132 commit 2bc4cc6

File tree

2 files changed

+46
-28
lines changed

2 files changed

+46
-28
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ private SelectBuilder.SelectWhere selectBuilder(Collection<SqlIdentifier> keyCol
514514

515515
Table table = getTable();
516516

517-
List<Expression> columnExpressions = new ArrayList<>();
517+
Set<Expression> columnExpressions = new LinkedHashSet<>();
518518

519519
List<Join> joinTables = new ArrayList<>();
520520
for (PersistentPropertyPath<RelationalPersistentProperty> path : mappingContext

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorUnitTests.java

+45-27
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.data.relational.core.mapping.AggregatePath;
4444
import org.springframework.data.relational.core.mapping.Column;
4545
import org.springframework.data.relational.core.mapping.DefaultNamingStrategy;
46+
import org.springframework.data.relational.core.mapping.MappedCollection;
4647
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
4748
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
4849
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@@ -388,7 +389,8 @@ void findAllByPropertyWithMultipartIdentifier() {
388389
void findAllByPropertyWithKey() {
389390

390391
// this would get called when ListParent is th element type of a Map
391-
String sql = sqlGenerator.getFindAllByProperty(BACKREF, new AggregatePath.ColumnInfo(unquoted("key-column"),unquoted("key-column")), false);
392+
String sql = sqlGenerator.getFindAllByProperty(BACKREF,
393+
new AggregatePath.ColumnInfo(unquoted("key-column"), unquoted("key-column")), false);
392394

393395
assertThat(sql).isEqualTo("SELECT dummy_entity.id1 AS id1, dummy_entity.x_name AS x_name, " //
394396
+ "dummy_entity.x_other AS x_other, " //
@@ -451,9 +453,9 @@ void findAllByPropertyWithEmptyBackrefColumn() {
451453
Identifier emptyIdentifier = Identifier.of(EMPTY, 0, Object.class);
452454
assertThatThrownBy(() -> sqlGenerator.getFindAllByProperty(emptyIdentifier,
453455
new AggregatePath.ColumnInfo(unquoted("key-column"), unquoted("key-column")), false)) //
454-
.isInstanceOf(IllegalArgumentException.class) //
455-
.hasMessageContaining(
456-
"An empty SqlIdentifier can't be used in condition. Make sure that all composite primary keys are defined in the query");
456+
.isInstanceOf(IllegalArgumentException.class) //
457+
.hasMessageContaining(
458+
"An empty SqlIdentifier can't be used in condition. Make sure that all composite primary keys are defined in the query");
457459
}
458460

459461
@Test // DATAJDBC-219
@@ -625,43 +627,43 @@ void deletingLongChain() {
625627

626628
assertThat(
627629
createSqlGenerator(Chain4.class).createDeleteByPath(getPath("chain3.chain2.chain1.chain0", Chain4.class))) //
628-
.isEqualTo("DELETE FROM chain0 " + //
629-
"WHERE chain0.chain1 IN (" + //
630-
"SELECT chain1.x_one " + //
631-
"FROM chain1 " + //
632-
"WHERE chain1.chain2 IN (" + //
633-
"SELECT chain2.x_two " + //
634-
"FROM chain2 " + //
635-
"WHERE chain2.chain3 IN (" + //
636-
"SELECT chain3.x_three " + //
637-
"FROM chain3 " + //
638-
"WHERE chain3.chain4 = :rootId" + //
639-
")))");
630+
.isEqualTo("DELETE FROM chain0 " + //
631+
"WHERE chain0.chain1 IN (" + //
632+
"SELECT chain1.x_one " + //
633+
"FROM chain1 " + //
634+
"WHERE chain1.chain2 IN (" + //
635+
"SELECT chain2.x_two " + //
636+
"FROM chain2 " + //
637+
"WHERE chain2.chain3 IN (" + //
638+
"SELECT chain3.x_three " + //
639+
"FROM chain3 " + //
640+
"WHERE chain3.chain4 = :rootId" + //
641+
")))");
640642
}
641643

642644
@Test // DATAJDBC-359
643645
void deletingLongChainNoId() {
644646

645647
assertThat(createSqlGenerator(NoIdChain4.class)
646648
.createDeleteByPath(getPath("chain3.chain2.chain1.chain0", NoIdChain4.class))) //
647-
.isEqualTo("DELETE FROM no_id_chain0 WHERE no_id_chain0.no_id_chain4 = :rootId");
649+
.isEqualTo("DELETE FROM no_id_chain0 WHERE no_id_chain0.no_id_chain4 = :rootId");
648650
}
649651

650652
@Test // DATAJDBC-359
651653
void deletingLongChainNoIdWithBackreferenceNotReferencingTheRoot() {
652654

653655
assertThat(createSqlGenerator(IdIdNoIdChain.class)
654656
.createDeleteByPath(getPath("idNoIdChain.chain4.chain3.chain2.chain1.chain0", IdIdNoIdChain.class))) //
655-
.isEqualTo( //
656-
"DELETE FROM no_id_chain0 " //
657-
+ "WHERE no_id_chain0.no_id_chain4 IN (" //
658-
+ "SELECT no_id_chain4.x_four " //
659-
+ "FROM no_id_chain4 " //
660-
+ "WHERE no_id_chain4.id_no_id_chain IN (" //
661-
+ "SELECT id_no_id_chain.x_id " //
662-
+ "FROM id_no_id_chain " //
663-
+ "WHERE id_no_id_chain.id_id_no_id_chain = :rootId" //
664-
+ "))");
657+
.isEqualTo( //
658+
"DELETE FROM no_id_chain0 " //
659+
+ "WHERE no_id_chain0.no_id_chain4 IN (" //
660+
+ "SELECT no_id_chain4.x_four " //
661+
+ "FROM no_id_chain4 " //
662+
+ "WHERE no_id_chain4.id_no_id_chain IN (" //
663+
+ "SELECT id_no_id_chain.x_id " //
664+
+ "FROM id_no_id_chain " //
665+
+ "WHERE id_no_id_chain.id_id_no_id_chain = :rootId" //
666+
+ "))");
665667
}
666668

667669
@Test // DATAJDBC-340
@@ -926,6 +928,16 @@ void keyColumnShouldIgnoreRenamedParent() {
926928
"WHERE referenced_entity.parentId");
927929
}
928930

931+
@Test // GH-1865
932+
void mappingMapKeyToChildShouldNotResultInDuplicateColumn() {
933+
934+
SqlGenerator sqlGenerator = createSqlGenerator(Child.class);
935+
String sql = sqlGenerator.getFindAllByProperty(Identifier.of(unquoted("parent"), 23, Parent.class),
936+
context.getAggregatePath(getPath("children", Parent.class)).getTableInfo().qualifierColumnInfo(), false);
937+
938+
assertThat(sql).containsOnlyOnce("child.NICK_NAME AS NICK_NAME");
939+
}
940+
929941
@Nullable
930942
private SqlIdentifier getAlias(Object maybeAliased) {
931943

@@ -1117,4 +1129,10 @@ static class IdIdNoIdChain {
11171129
@Id Long id;
11181130
IdNoIdChain idNoIdChain;
11191131
}
1132+
1133+
record Parent(@Id Long id, String name, @MappedCollection(keyColumn = "NICK_NAME") Map<String, Child> children) {
1134+
}
1135+
1136+
record Child(@Column("NICK_NAME") String nickName, String name) {
1137+
}
11201138
}

0 commit comments

Comments
 (0)