Skip to content

Commit 9e12d0a

Browse files
schaudermp911de
authored andcommitted
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
1 parent 97cf38f commit 9e12d0a

11 files changed

+272
-39
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,10 @@ public <T> T getPropertyValue(RelationalPersistentProperty property) {
385385
if (idDefiningParentPath.hasIdProperty()) {
386386

387387
Class<?> idType = idDefiningParentPath.getRequiredIdProperty().getActualType();
388-
SqlIdentifier parentId = idDefiningParentPath.getTableInfo().idColumnName();
389-
Object idValue = this.identifier.get(parentId);
388+
//
389+
RelationalPersistentProperty requiredIdProperty = idDefiningParentPath.getRequiredIdProperty();
390+
AggregatePath idPath = idDefiningParentPath.append(requiredIdProperty);
391+
Object idValue = delegate.getValue(idPath);
390392

391393
Assert.state(idValue != null, "idValue must not be null at this point");
392394

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

+48-13
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,12 @@
2222
import static org.springframework.data.jdbc.testing.TestDatabaseFeatures.Feature.*;
2323

2424
import java.time.LocalDateTime;
25+
import java.util.*;
2526
import java.util.ArrayList;
26-
import java.util.Collections;
27-
import java.util.HashMap;
28-
import java.util.HashSet;
29-
import java.util.Iterator;
30-
import java.util.List;
31-
import java.util.Map;
32-
import java.util.Objects;
33-
import java.util.Optional;
34-
import java.util.Set;
3527
import java.util.function.Function;
3628
import java.util.stream.IntStream;
3729

30+
import org.assertj.core.api.SoftAssertions;
3831
import org.junit.jupiter.api.Test;
3932
import org.springframework.beans.factory.annotation.Autowired;
4033
import org.springframework.context.ApplicationEventPublisher;
@@ -919,7 +912,7 @@ void readOnlyGetsLoadedButNotWritten() {
919912

920913
assertThat(
921914
jdbcTemplate.queryForObject("SELECT read_only FROM with_read_only", Collections.emptyMap(), String.class))
922-
.isEqualTo("from-db");
915+
.isEqualTo("from-db");
923916
}
924917

925918
@Test
@@ -1258,15 +1251,16 @@ void recordOfSet() {
12581251
@Test // GH-1656
12591252
void mapWithEnumKey() {
12601253

1261-
EnumMapOwner enumMapOwner = template.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
1254+
EnumMapOwner enumMapOwner = template
1255+
.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element"))));
12621256

12631257
Iterable<EnumMapOwner> enumMapOwners = template.findAll(EnumMapOwner.class);
12641258

12651259
assertThat(enumMapOwners).containsExactly(enumMapOwner);
12661260
}
12671261

12681262
@Test // GH-1684
1269-
void oneToOneWithIdenticalIdColumnName(){
1263+
void oneToOneWithIdenticalIdColumnName() {
12701264

12711265
WithOneToOne saved = template.insert(new WithOneToOne("one", new Referenced(23L)));
12721266

@@ -1275,6 +1269,37 @@ void oneToOneWithIdenticalIdColumnName(){
12751269
assertThat(reloaded).isEqualTo(saved);
12761270
}
12771271

1272+
@Test // GH-1802
1273+
void singleEntitySetChain() {
1274+
1275+
First first1 = template.insert( //
1276+
new First(1L, "first-1", //
1277+
new Sec(2L, "second-1-2", Set.of( //
1278+
new Third("third-1-2-0"), //
1279+
new Third("third-1-2-1"), //
1280+
new Third("third-1-2-3")) //
1281+
) //
1282+
) //
1283+
);
1284+
First first2 = template.insert( //
1285+
new First(2L, "first-2", //
1286+
new Sec(3L, "second-2-3", Set.of( //
1287+
new Third("third-2-3-0"), //
1288+
new Third("third-2-3-1"), //
1289+
new Third("third-2-3-3")) //
1290+
) //
1291+
) //
1292+
);
1293+
1294+
First first1Reloaded = template.findById(first1.id, First.class);
1295+
First first2Reloaded = template.findById(first2.id, First.class);
1296+
1297+
SoftAssertions.assertSoftly(softly ->{
1298+
softly.assertThat(first1Reloaded).isEqualTo(first1);
1299+
softly.assertThat(first2Reloaded).isEqualTo(first2);
1300+
});
1301+
}
1302+
12781303
private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate,
12791304
Function<Number, T> toConcreteNumber) {
12801305
saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0);
@@ -2096,11 +2121,21 @@ record Book(String name) {
20962121
record EnumMapOwner(@Id Long id, String name, Map<Color, MapElement> map) {
20972122
}
20982123

2099-
record WithOneToOne(@Id String id,@MappedCollection(idColumn = "renamed") Referenced referenced){}
2124+
record WithOneToOne(@Id String id, @MappedCollection(idColumn = "renamed") Referenced referenced) {
2125+
}
21002126

21012127
record Referenced(@Id Long id) {
21022128
}
21032129

2130+
record First(@Id Long id, String name, Sec sec) {
2131+
}
2132+
2133+
record Sec(@Id Long id, String name, Set<Third> thirds) {
2134+
}
2135+
2136+
record Third(String name) {
2137+
}
2138+
21042139
@Configuration
21052140
@Import(TestConfiguration.class)
21062141
static class Config {

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

+24
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ DROP TABLE ENUM_MAP_OWNER;
5555
DROP TABLE REFERENCED;
5656
DROP TABLE WITH_ONE_TO_ONE;
5757

58+
DROP TABLE THIRD;
59+
DROP TABLE SEC;
60+
DROP TABLE FIRST;
5861

5962
CREATE TABLE LEGO_SET
6063
(
@@ -444,3 +447,24 @@ CREATE TABLE REFERENCED
444447
"renamed" VARCHAR(100),
445448
ID BIGINT
446449
);
450+
451+
CREATE TABLE FIRST
452+
(
453+
ID BIGINT NOT NULL PRIMARY KEY,
454+
NAME VARCHAR(20) NOT NULL
455+
);
456+
457+
CREATE TABLE SEC
458+
(
459+
ID BIGINT NOT NULL PRIMARY KEY,
460+
FIRST BIGINT NOT NULL,
461+
NAME VARCHAR(20) NOT NULL,
462+
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
463+
);
464+
465+
CREATE TABLE THIRD
466+
(
467+
SEC BIGINT NOT NULL,
468+
NAME VARCHAR(20) NOT NULL,
469+
FOREIGN KEY (SEC) REFERENCES SEC (ID)
470+
);

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

+45-24
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ CREATE TABLE LEGO_SET
55
);
66
CREATE TABLE MANUAL
77
(
8-
"id2" SERIAL PRIMARY KEY,
9-
LEGO_SET BIGINT,
8+
"id2" SERIAL PRIMARY KEY,
9+
LEGO_SET BIGINT,
1010
"alternative" BIGINT,
11-
CONTENT VARCHAR(2000)
11+
CONTENT VARCHAR(2000)
1212
);
1313

1414
ALTER TABLE MANUAL
@@ -34,17 +34,17 @@ CREATE TABLE LIST_PARENT
3434

3535
CREATE TABLE SIMPLE_LIST_PARENT
3636
(
37-
ID SERIAL PRIMARY KEY,
38-
NAME VARCHAR(100)
37+
ID SERIAL PRIMARY KEY,
38+
NAME VARCHAR(100)
3939
);
4040

4141
CREATE TABLE element_no_id
4242
(
43-
content VARCHAR(100),
43+
content VARCHAR(100),
4444
SIMPLE_LIST_PARENT_key BIGINT,
4545
SIMPLE_LIST_PARENT INTEGER,
46-
LIST_PARENT_key BIGINT,
47-
LIST_PARENT INTEGER
46+
LIST_PARENT_key BIGINT,
47+
LIST_PARENT INTEGER
4848
);
4949

5050
CREATE TABLE "ARRAY_OWNER"
@@ -62,14 +62,14 @@ CREATE TABLE BYTE_ARRAY_OWNER
6262

6363
CREATE TABLE DOUBLE_LIST_OWNER
6464
(
65-
ID SERIAL PRIMARY KEY,
66-
DIGITS DOUBLE ARRAY[10]
65+
ID SERIAL PRIMARY KEY,
66+
DIGITS DOUBLE ARRAY[10]
6767
);
6868

6969
CREATE TABLE FLOAT_LIST_OWNER
7070
(
71-
ID SERIAL PRIMARY KEY,
72-
DIGITS FLOAT ARRAY[10]
71+
ID SERIAL PRIMARY KEY,
72+
DIGITS FLOAT ARRAY[10]
7373
);
7474

7575
CREATE TABLE CHAIN4
@@ -338,36 +338,36 @@ CREATE TABLE WITH_ID_ONLY
338338

339339
CREATE TABLE WITH_INSERT_ONLY
340340
(
341-
ID SERIAL PRIMARY KEY,
341+
ID SERIAL PRIMARY KEY,
342342
INSERT_ONLY VARCHAR(100)
343343
);
344344

345345
CREATE TABLE MULTIPLE_COLLECTIONS
346346
(
347-
ID SERIAL PRIMARY KEY,
347+
ID SERIAL PRIMARY KEY,
348348
NAME VARCHAR(100)
349349
);
350350

351351
CREATE TABLE SET_ELEMENT
352352
(
353353
MULTIPLE_COLLECTIONS BIGINT,
354-
NAME VARCHAR(100)
354+
NAME VARCHAR(100)
355355
);
356356

357357
CREATE TABLE LIST_ELEMENT
358358
(
359-
MULTIPLE_COLLECTIONS BIGINT,
359+
MULTIPLE_COLLECTIONS BIGINT,
360360
MULTIPLE_COLLECTIONS_KEY INT,
361-
NAME VARCHAR(100)
361+
NAME VARCHAR(100)
362362
);
363363

364364
CREATE TABLE MAP_ELEMENT
365365
(
366-
MULTIPLE_COLLECTIONS BIGINT,
366+
MULTIPLE_COLLECTIONS BIGINT,
367367
MULTIPLE_COLLECTIONS_KEY VARCHAR(10),
368-
ENUM_MAP_OWNER BIGINT,
369-
ENUM_MAP_OWNER_KEY VARCHAR(10),
370-
NAME VARCHAR(100)
368+
ENUM_MAP_OWNER BIGINT,
369+
ENUM_MAP_OWNER_KEY VARCHAR(10),
370+
NAME VARCHAR(100)
371371
);
372372

373373
CREATE TABLE AUTHOR
@@ -378,12 +378,12 @@ CREATE TABLE AUTHOR
378378
CREATE TABLE BOOK
379379
(
380380
AUTHOR BIGINT,
381-
NAME VARCHAR(100)
381+
NAME VARCHAR(100)
382382
);
383383

384384
CREATE TABLE ENUM_MAP_OWNER
385385
(
386-
ID SERIAL PRIMARY KEY,
386+
ID SERIAL PRIMARY KEY,
387387
NAME VARCHAR(100)
388388
);
389389

@@ -395,5 +395,26 @@ CREATE TABLE WITH_ONE_TO_ONE
395395
CREATE TABLE REFERENCED
396396
(
397397
"renamed" VARCHAR(100),
398-
ID BIGINT
398+
ID BIGINT
399+
);
400+
401+
CREATE TABLE FIRST
402+
(
403+
ID BIGINT NOT NULL PRIMARY KEY,
404+
NAME VARCHAR(20) NOT NULL
399405
);
406+
407+
CREATE TABLE SEC
408+
(
409+
ID BIGINT NOT NULL PRIMARY KEY,
410+
FIRST BIGINT NOT NULL,
411+
NAME VARCHAR(20) NOT NULL,
412+
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
413+
);
414+
415+
CREATE TABLE THIRD
416+
(
417+
SEC BIGINT NOT NULL,
418+
NAME VARCHAR(20) NOT NULL,
419+
FOREIGN KEY (SEC) REFERENCES SEC (ID)
420+
);

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

+21
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,24 @@ CREATE TABLE REFERENCED
399399
"renamed" VARCHAR(100),
400400
ID BIGINT
401401
);
402+
403+
CREATE TABLE FIRST
404+
(
405+
ID BIGINT NOT NULL PRIMARY KEY,
406+
NAME VARCHAR(20) NOT NULL
407+
);
408+
409+
CREATE TABLE SEC
410+
(
411+
ID BIGINT NOT NULL PRIMARY KEY,
412+
FIRST BIGINT NOT NULL,
413+
NAME VARCHAR(20) NOT NULL,
414+
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
415+
);
416+
417+
CREATE TABLE THIRD
418+
(
419+
SEC BIGINT NOT NULL,
420+
NAME VARCHAR(20) NOT NULL,
421+
FOREIGN KEY (SEC) REFERENCES SEC (ID)
422+
);

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

+21
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,24 @@ CREATE TABLE REFERENCED
371371
`renamed` VARCHAR(100),
372372
ID BIGINT
373373
);
374+
375+
CREATE TABLE FIRST
376+
(
377+
ID BIGINT NOT NULL PRIMARY KEY,
378+
NAME VARCHAR(20) NOT NULL
379+
);
380+
381+
CREATE TABLE SEC
382+
(
383+
ID BIGINT NOT NULL PRIMARY KEY,
384+
FIRST BIGINT NOT NULL,
385+
NAME VARCHAR(20) NOT NULL,
386+
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
387+
);
388+
389+
CREATE TABLE THIRD
390+
(
391+
SEC BIGINT NOT NULL,
392+
NAME VARCHAR(20) NOT NULL,
393+
FOREIGN KEY (SEC) REFERENCES SEC (ID)
394+
);

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

+25
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,28 @@ CREATE TABLE REFERENCED
417417
"renamed" VARCHAR(100),
418418
ID BIGINT
419419
);
420+
421+
DROP TABLE THIRD;
422+
DROP TABLE SEC;
423+
DROP TABLE FIRST;
424+
425+
CREATE TABLE FIRST
426+
(
427+
ID BIGINT NOT NULL PRIMARY KEY,
428+
NAME VARCHAR(20) NOT NULL
429+
);
430+
431+
CREATE TABLE SEC
432+
(
433+
ID BIGINT NOT NULL PRIMARY KEY,
434+
FIRST BIGINT NOT NULL,
435+
NAME VARCHAR(20) NOT NULL,
436+
FOREIGN KEY (FIRST) REFERENCES FIRST (ID)
437+
);
438+
439+
CREATE TABLE THIRD
440+
(
441+
SEC BIGINT NOT NULL,
442+
NAME VARCHAR(20) NOT NULL,
443+
FOREIGN KEY (SEC) REFERENCES SEC (ID)
444+
);

0 commit comments

Comments
 (0)