Skip to content

Commit fd662bf

Browse files
committed
Avoid duplicate selection of columns.
When the key column of a MappedCollection is also present in the contained entity that column got select twice. We now check if the column already gets selected before adding it to the selection. This only works properly if the column names derived for the entity property and the key column match exactly, which might require use of a `@Column` annotation depending on the used NamingStrategy. Closes #1073 Original pull request #1074
1 parent 0d1ba21 commit fd662bf

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

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

+18
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,23 @@ void findAllByPropertyWithKeyOrdered() {
423423
+ "ORDER BY key-column");
424424
}
425425

426+
@Test // GH-1073
427+
public void findAllByPropertyAvoidsDuplicateColumns() {
428+
429+
final SqlGenerator sqlGenerator = createSqlGenerator(ReferencedEntity.class);
430+
final String sql = sqlGenerator.getFindAllByProperty(
431+
Identifier.of(quoted("id"), "parent-id-value", DummyEntity.class), //
432+
quoted("X_L1ID"), // this key column collides with the name derived by the naming strategy for the id of
433+
// ReferencedEntity.
434+
false);
435+
436+
final String id = "referenced_entity.x_l1id AS x_l1id";
437+
assertThat(sql.indexOf(id)) //
438+
.describedAs(sql) //
439+
.isEqualTo(sql.lastIndexOf(id));
440+
441+
}
442+
426443
@Test // DATAJDBC-219
427444
void updateWithVersion() {
428445

@@ -862,6 +879,7 @@ static class DummyEntity {
862879
Set<Element> elements;
863880
Map<Integer, Element> mappedElements;
864881
AggregateReference<OtherAggregate, Long> other;
882+
Map<Long, ReferencedEntity> mappedReference;
865883
}
866884

867885
@SuppressWarnings("unused")

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

+44
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.springframework.data.relational.core.sql;
1717

18+
import java.util.Objects;
19+
1820
import org.springframework.lang.Nullable;
1921
import org.springframework.util.Assert;
2022

@@ -357,6 +359,27 @@ String getPrefix() {
357359
return prefix;
358360
}
359361

362+
@Override
363+
public boolean equals(Object o) {
364+
365+
if (this == o) {
366+
return true;
367+
}
368+
if (o == null || getClass() != o.getClass()) {
369+
return false;
370+
}
371+
if (!super.equals(o)) {
372+
return false;
373+
}
374+
Column column = (Column) o;
375+
return name.equals(column.name) && table.equals(column.table);
376+
}
377+
378+
@Override
379+
public int hashCode() {
380+
return Objects.hash(super.hashCode(), name, table);
381+
}
382+
360383
/**
361384
* {@link Aliased} {@link Column} implementation.
362385
*/
@@ -396,5 +419,26 @@ public Column from(Table table) {
396419
public String toString() {
397420
return getPrefix() + getName() + " AS " + getAlias();
398421
}
422+
423+
@Override
424+
public boolean equals(Object o) {
425+
426+
if (this == o) {
427+
return true;
428+
}
429+
if (o == null || getClass() != o.getClass()) {
430+
return false;
431+
}
432+
if (!super.equals(o)) {
433+
return false;
434+
}
435+
AliasedColumn that = (AliasedColumn) o;
436+
return alias.equals(that.alias);
437+
}
438+
439+
@Override
440+
public int hashCode() {
441+
return Objects.hash(super.hashCode(), alias);
442+
}
399443
}
400444
}

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

+45-1
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@
1515
*/
1616
package org.springframework.data.relational.core.sql;
1717

18+
import java.util.Objects;
19+
1820
import org.springframework.util.Assert;
1921

2022
/**
21-
* Represents a table reference within a SQL statement. Typically used to denote {@code FROM} or {@code JOIN} or to
23+
* Represents a table reference within a SQL statement. Typically, used to denote {@code FROM} or {@code JOIN} or to
2224
* prefix a {@link Column}.
2325
* <p>
2426
* Renders to: {@code <name>} or {@code <name> AS <name>}.
2527
* </p>
2628
*
2729
* @author Mark Paluch
30+
* @author Jens Schauder
2831
* @since 1.1
2932
*/
3033
public class Table extends AbstractSegment implements TableLike {
@@ -127,6 +130,26 @@ public String toString() {
127130
return name.toString();
128131
}
129132

133+
@Override
134+
public boolean equals(Object o) {
135+
if (this == o) {
136+
return true;
137+
}
138+
if (o == null || getClass() != o.getClass()) {
139+
return false;
140+
}
141+
if (!super.equals(o)) {
142+
return false;
143+
}
144+
Table table = (Table) o;
145+
return name.equals(table.name);
146+
}
147+
148+
@Override
149+
public int hashCode() {
150+
return Objects.hash(super.hashCode(), name);
151+
}
152+
130153
/**
131154
* {@link Aliased} {@link Table} implementation.
132155
*/
@@ -164,5 +187,26 @@ public SqlIdentifier getReferenceName() {
164187
public String toString() {
165188
return getName() + " AS " + getAlias();
166189
}
190+
191+
@Override
192+
public boolean equals(Object o) {
193+
194+
if (this == o) {
195+
return true;
196+
}
197+
if (o == null || getClass() != o.getClass()) {
198+
return false;
199+
}
200+
if (!super.equals(o)) {
201+
return false;
202+
}
203+
AliasedTable that = (AliasedTable) o;
204+
return alias.equals(that.alias);
205+
}
206+
207+
@Override
208+
public int hashCode() {
209+
return Objects.hash(super.hashCode(), alias);
210+
}
167211
}
168212
}

0 commit comments

Comments
 (0)