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
This commit is contained in:
Jens Schauder
2021-10-21 15:39:36 +02:00
parent 0d1ba211c5
commit fd662bf9e6
3 changed files with 107 additions and 1 deletions

View File

@@ -423,6 +423,23 @@ class SqlGeneratorUnitTests {
+ "ORDER BY key-column");
}
@Test // GH-1073
public void findAllByPropertyAvoidsDuplicateColumns() {
final SqlGenerator sqlGenerator = createSqlGenerator(ReferencedEntity.class);
final String sql = sqlGenerator.getFindAllByProperty(
Identifier.of(quoted("id"), "parent-id-value", DummyEntity.class), //
quoted("X_L1ID"), // this key column collides with the name derived by the naming strategy for the id of
// ReferencedEntity.
false);
final String id = "referenced_entity.x_l1id AS x_l1id";
assertThat(sql.indexOf(id)) //
.describedAs(sql) //
.isEqualTo(sql.lastIndexOf(id));
}
@Test // DATAJDBC-219
void updateWithVersion() {
@@ -862,6 +879,7 @@ class SqlGeneratorUnitTests {
Set<Element> elements;
Map<Integer, Element> mappedElements;
AggregateReference<OtherAggregate, Long> other;
Map<Long, ReferencedEntity> mappedReference;
}
@SuppressWarnings("unused")

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.relational.core.sql;
import java.util.Objects;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -357,6 +359,27 @@ public class Column extends AbstractSegment implements Expression, Named {
return prefix;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
Column column = (Column) o;
return name.equals(column.name) && table.equals(column.table);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), name, table);
}
/**
* {@link Aliased} {@link Column} implementation.
*/
@@ -396,5 +419,26 @@ public class Column extends AbstractSegment implements Expression, Named {
public String toString() {
return getPrefix() + getName() + " AS " + getAlias();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
AliasedColumn that = (AliasedColumn) o;
return alias.equals(that.alias);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), alias);
}
}
}

View File

@@ -15,16 +15,19 @@
*/
package org.springframework.data.relational.core.sql;
import java.util.Objects;
import org.springframework.util.Assert;
/**
* Represents a table reference within a SQL statement. Typically used to denote {@code FROM} or {@code JOIN} or to
* Represents a table reference within a SQL statement. Typically, used to denote {@code FROM} or {@code JOIN} or to
* prefix a {@link Column}.
* <p>
* Renders to: {@code <name>} or {@code <name> AS <name>}.
* </p>
*
* @author Mark Paluch
* @author Jens Schauder
* @since 1.1
*/
public class Table extends AbstractSegment implements TableLike {
@@ -127,6 +130,26 @@ public class Table extends AbstractSegment implements TableLike {
return name.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
Table table = (Table) o;
return name.equals(table.name);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), name);
}
/**
* {@link Aliased} {@link Table} implementation.
*/
@@ -164,5 +187,26 @@ public class Table extends AbstractSegment implements TableLike {
public String toString() {
return getName() + " AS " + getAlias();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
AliasedTable that = (AliasedTable) o;
return alias.equals(that.alias);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), alias);
}
}
}