Browse Source

Fix usage of wrong id value in related selects.

In an aggregate A->B-Collection<C> a select gets executed for loading Collection<C>.
That select used the wrong ID when B had an ID with the same name as A.

This is now fixed.

Closes #1802
Original pull request: #1810
pull/1816/head
Jens Schauder 2 years ago committed by Mark Paluch
parent
commit
9e12d0acd5
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 6
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
  2. 61
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
  3. 24
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql
  4. 69
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql
  5. 21
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql
  6. 21
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql
  7. 25
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql
  8. 21
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql
  9. 24
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql
  10. 25
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql
  11. 14
      spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/DefaultAggregatePathUnitTests.java

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

@ -385,8 +385,10 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements @@ -385,8 +385,10 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
if (idDefiningParentPath.hasIdProperty()) {
Class<?> idType = idDefiningParentPath.getRequiredIdProperty().getActualType();
SqlIdentifier parentId = idDefiningParentPath.getTableInfo().idColumnName();
Object idValue = this.identifier.get(parentId);
//
RelationalPersistentProperty requiredIdProperty = idDefiningParentPath.getRequiredIdProperty();
AggregatePath idPath = idDefiningParentPath.append(requiredIdProperty);
Object idValue = delegate.getValue(idPath);
Assert.state(idValue != null, "idValue must not be null at this point");

61
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java

@ -22,19 +22,12 @@ import static org.springframework.data.jdbc.testing.TestConfiguration.*; @@ -22,19 +22,12 @@ import static org.springframework.data.jdbc.testing.TestConfiguration.*;
import static org.springframework.data.jdbc.testing.TestDatabaseFeatures.Feature.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
@ -919,7 +912,7 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests { @@ -919,7 +912,7 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
assertThat(
jdbcTemplate.queryForObject("SELECT read_only FROM with_read_only", Collections.emptyMap(), String.class))
.isEqualTo("from-db");
.isEqualTo("from-db");
}
@Test
@ -1258,7 +1251,8 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests { @@ -1258,7 +1251,8 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
@Test // GH-1656
void mapWithEnumKey() {
EnumMapOwner enumMapOwner = template.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
EnumMapOwner enumMapOwner = template
.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
Iterable<EnumMapOwner> enumMapOwners = template.findAll(EnumMapOwner.class);
@ -1266,7 +1260,7 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests { @@ -1266,7 +1260,7 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
}
@Test // GH-1684
void oneToOneWithIdenticalIdColumnName(){
void oneToOneWithIdenticalIdColumnName() {
WithOneToOne saved = template.insert(new WithOneToOne("one", new Referenced(23L)));
@ -1275,6 +1269,37 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests { @@ -1275,6 +1269,37 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
assertThat(reloaded).isEqualTo(saved);
}
@Test // GH-1802
void singleEntitySetChain() {
First first1 = template.insert( //
new First(1L, "first-1", //
new Sec(2L, "second-1-2", Set.of( //
new Third("third-1-2-0"), //
new Third("third-1-2-1"), //
new Third("third-1-2-3")) //
) //
) //
);
First first2 = template.insert( //
new First(2L, "first-2", //
new Sec(3L, "second-2-3", Set.of( //
new Third("third-2-3-0"), //
new Third("third-2-3-1"), //
new Third("third-2-3-3")) //
) //
) //
);
First first1Reloaded = template.findById(first1.id, First.class);
First first2Reloaded = template.findById(first2.id, First.class);
SoftAssertions.assertSoftly(softly ->{
softly.assertThat(first1Reloaded).isEqualTo(first1);
softly.assertThat(first2Reloaded).isEqualTo(first2);
});
}
private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate,
Function<Number, T> toConcreteNumber) {
saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0);
@ -2096,11 +2121,21 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests { @@ -2096,11 +2121,21 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
record EnumMapOwner(@Id Long id, String name, Map<Color, MapElement> map) {
}
record WithOneToOne(@Id String id,@MappedCollection(idColumn = "renamed") Referenced referenced){}
record WithOneToOne(@Id String id, @MappedCollection(idColumn = "renamed") Referenced referenced) {
}
record Referenced(@Id Long id) {
}
record First(@Id Long id, String name, Sec sec) {
}
record Sec(@Id Long id, String name, Set<Third> thirds) {
}
record Third(String name) {
}
@Configuration
@Import(TestConfiguration.class)
static class Config {

24
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql

@ -55,6 +55,9 @@ DROP TABLE ENUM_MAP_OWNER; @@ -55,6 +55,9 @@ DROP TABLE ENUM_MAP_OWNER;
DROP TABLE REFERENCED;
DROP TABLE WITH_ONE_TO_ONE;
DROP TABLE THIRD;
DROP TABLE SEC;
DROP TABLE FIRST;
CREATE TABLE LEGO_SET
(
@ -444,3 +447,24 @@ CREATE TABLE REFERENCED @@ -444,3 +447,24 @@ CREATE TABLE REFERENCED
"renamed" VARCHAR(100),
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

69
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql

@ -5,10 +5,10 @@ CREATE TABLE LEGO_SET @@ -5,10 +5,10 @@ CREATE TABLE LEGO_SET
);
CREATE TABLE MANUAL
(
"id2" SERIAL PRIMARY KEY,
LEGO_SET BIGINT,
"id2" SERIAL PRIMARY KEY,
LEGO_SET BIGINT,
"alternative" BIGINT,
CONTENT VARCHAR(2000)
CONTENT VARCHAR(2000)
);
ALTER TABLE MANUAL
@ -34,17 +34,17 @@ CREATE TABLE LIST_PARENT @@ -34,17 +34,17 @@ CREATE TABLE LIST_PARENT
CREATE TABLE SIMPLE_LIST_PARENT
(
ID SERIAL PRIMARY KEY,
NAME VARCHAR(100)
ID SERIAL PRIMARY KEY,
NAME VARCHAR(100)
);
CREATE TABLE element_no_id
(
content VARCHAR(100),
content VARCHAR(100),
SIMPLE_LIST_PARENT_key BIGINT,
SIMPLE_LIST_PARENT INTEGER,
LIST_PARENT_key BIGINT,
LIST_PARENT INTEGER
LIST_PARENT_key BIGINT,
LIST_PARENT INTEGER
);
CREATE TABLE "ARRAY_OWNER"
@ -62,14 +62,14 @@ CREATE TABLE BYTE_ARRAY_OWNER @@ -62,14 +62,14 @@ CREATE TABLE BYTE_ARRAY_OWNER
CREATE TABLE DOUBLE_LIST_OWNER
(
ID SERIAL PRIMARY KEY,
DIGITS DOUBLE ARRAY[10]
ID SERIAL PRIMARY KEY,
DIGITS DOUBLE ARRAY[10]
);
CREATE TABLE FLOAT_LIST_OWNER
(
ID SERIAL PRIMARY KEY,
DIGITS FLOAT ARRAY[10]
ID SERIAL PRIMARY KEY,
DIGITS FLOAT ARRAY[10]
);
CREATE TABLE CHAIN4
@ -338,36 +338,36 @@ CREATE TABLE WITH_ID_ONLY @@ -338,36 +338,36 @@ CREATE TABLE WITH_ID_ONLY
CREATE TABLE WITH_INSERT_ONLY
(
ID SERIAL PRIMARY KEY,
ID SERIAL PRIMARY KEY,
INSERT_ONLY VARCHAR(100)
);
CREATE TABLE MULTIPLE_COLLECTIONS
(
ID SERIAL PRIMARY KEY,
ID SERIAL PRIMARY KEY,
NAME VARCHAR(100)
);
CREATE TABLE SET_ELEMENT
(
MULTIPLE_COLLECTIONS BIGINT,
NAME VARCHAR(100)
NAME VARCHAR(100)
);
CREATE TABLE LIST_ELEMENT
(
MULTIPLE_COLLECTIONS BIGINT,
MULTIPLE_COLLECTIONS BIGINT,
MULTIPLE_COLLECTIONS_KEY INT,
NAME VARCHAR(100)
NAME VARCHAR(100)
);
CREATE TABLE MAP_ELEMENT
(
MULTIPLE_COLLECTIONS BIGINT,
MULTIPLE_COLLECTIONS BIGINT,
MULTIPLE_COLLECTIONS_KEY VARCHAR(10),
ENUM_MAP_OWNER BIGINT,
ENUM_MAP_OWNER_KEY VARCHAR(10),
NAME VARCHAR(100)
ENUM_MAP_OWNER BIGINT,
ENUM_MAP_OWNER_KEY VARCHAR(10),
NAME VARCHAR(100)
);
CREATE TABLE AUTHOR
@ -378,12 +378,12 @@ CREATE TABLE AUTHOR @@ -378,12 +378,12 @@ CREATE TABLE AUTHOR
CREATE TABLE BOOK
(
AUTHOR BIGINT,
NAME VARCHAR(100)
NAME VARCHAR(100)
);
CREATE TABLE ENUM_MAP_OWNER
(
ID SERIAL PRIMARY KEY,
ID SERIAL PRIMARY KEY,
NAME VARCHAR(100)
);
@ -395,5 +395,26 @@ CREATE TABLE WITH_ONE_TO_ONE @@ -395,5 +395,26 @@ CREATE TABLE WITH_ONE_TO_ONE
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

21
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql

@ -399,3 +399,24 @@ CREATE TABLE REFERENCED @@ -399,3 +399,24 @@ CREATE TABLE REFERENCED
"renamed" VARCHAR(100),
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

21
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql

@ -371,3 +371,24 @@ CREATE TABLE REFERENCED @@ -371,3 +371,24 @@ CREATE TABLE REFERENCED
`renamed` VARCHAR(100),
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

25
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql

@ -417,3 +417,28 @@ CREATE TABLE REFERENCED @@ -417,3 +417,28 @@ CREATE TABLE REFERENCED
"renamed" VARCHAR(100),
ID BIGINT
);
DROP TABLE THIRD;
DROP TABLE SEC;
DROP TABLE FIRST;
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

21
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql

@ -377,3 +377,24 @@ CREATE TABLE REFERENCED @@ -377,3 +377,24 @@ CREATE TABLE REFERENCED
`renamed` VARCHAR(100),
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

24
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql

@ -45,6 +45,10 @@ DROP TABLE ENUM_MAP_OWNER CASCADE CONSTRAINTS PURGE; @@ -45,6 +45,10 @@ DROP TABLE ENUM_MAP_OWNER CASCADE CONSTRAINTS PURGE;
DROP TABLE REFERENCED CASCADE CONSTRAINTS PURGE;
DROP TABLE WITH_ONE_TO_ONE CASCADE CONSTRAINTS PURGE;
DROP TABLE THIRD CASCADE CONSTRAINTS PURGE;
DROP TABLE SEC CASCADE CONSTRAINTS PURGE;
DROP TABLE FIRST CASCADE CONSTRAINTS PURGE;
CREATE TABLE LEGO_SET
(
"id1" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY,
@ -424,3 +428,23 @@ CREATE TABLE REFERENCED @@ -424,3 +428,23 @@ CREATE TABLE REFERENCED
"renamed" VARCHAR(100),
ID NUMBER
);
CREATE TABLE FIRST
(
ID NUMBER NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID NUMBER NOT NULL PRIMARY KEY,
FIRST NUMBER NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC NUMBER NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

25
spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql

@ -48,6 +48,10 @@ DROP TABLE ENUM_MAP_OWNER; @@ -48,6 +48,10 @@ DROP TABLE ENUM_MAP_OWNER;
DROP TABLE REFERENCED;
DROP TABLE WITH_ONE_TO_ONE;
DROP TABLE THIRD;
DROP TABLE SEC;
DROP TABLE FIRST;
CREATE TABLE LEGO_SET
(
"id1" SERIAL PRIMARY KEY,
@ -446,3 +450,24 @@ CREATE TABLE REFERENCED @@ -446,3 +450,24 @@ CREATE TABLE REFERENCED
"renamed" VARCHAR(100),
ID BIGINT
);
CREATE TABLE FIRST
(
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(20) NOT NULL
);
CREATE TABLE SEC
(
ID BIGINT NOT NULL PRIMARY KEY,
FIRST BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
);
CREATE TABLE THIRD
(
SEC BIGINT NOT NULL,
NAME VARCHAR(20) NOT NULL,
FOREIGN KEY (SEC) REFERENCES SEC (ID)
);

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

@ -467,6 +467,20 @@ class DefaultAggregatePathUnitTests { @@ -467,6 +467,20 @@ class DefaultAggregatePathUnitTests {
});
}
@Test // GH-1802
void dingens() {
assertSoftly(softly -> {
AggregatePath.TableInfo tableInfo = path("withId.second.third").getTableInfo();
AggregatePath idDefiningParentPath = path("withId.second.third").getIdDefiningParentPath();
AggregatePath.TableInfo parentTable = idDefiningParentPath.getTableInfo();
softly.assertThat(tableInfo.effectiveIdColumnName())
.isEqualTo(quoted("WITH_ID"));
});
}
@Test // GH-1525
void getLength() {

Loading…
Cancel
Save