Browse Source

Fix access of root property instead of child property.

When the child of a one-to-one relationship has an id, the value for that id gets read in the wrong way.
We get the column name for that id use that to access the value in the RowDocument.

This results in either no value at all being found or even worse, the value of a root entity with a property of same name being accessed.

This is fixed by using the full AggregatePath instead of just the property for accessing that value.

Closes #1684
Original pull request: #1775
pull/1781/head
Jens Schauder 2 years ago committed by Mark Paluch
parent
commit
8a94345a7a
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 2
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverter.java
  2. 14
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java
  3. 20
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/MappingJdbcConverterUnitTests.java
  4. 15
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql
  5. 11
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql
  6. 12
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql
  7. 11
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql
  8. 15
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql
  9. 12
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql
  10. 14
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql
  11. 14
      spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql

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

@ -327,7 +327,7 @@ public class MappingJdbcConverter extends MappingRelationalConverter implements
this.accessor = accessor; this.accessor = accessor;
this.context = context; this.context = context;
this.identifier = path.isEntity() this.identifier = path.isEntity()
? potentiallyAppendIdentifier(identifier, path.getRequiredLeafEntity(), delegate::getPropertyValue) ? potentiallyAppendIdentifier(identifier, path.getRequiredLeafEntity(), property -> delegate.getValue(path.append(property)))
: identifier; : identifier;
} }

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

@ -1265,6 +1265,16 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
assertThat(enumMapOwners).containsExactly(enumMapOwner); assertThat(enumMapOwners).containsExactly(enumMapOwner);
} }
@Test // GH-1684
void oneToOneWithIdenticalIdColumnName(){
WithOneToOne saved = template.insert(new WithOneToOne("one", new Referenced(23L)));
WithOneToOne reloaded = template.findById(saved.id, WithOneToOne.class);
assertThat(reloaded).isEqualTo(saved);
}
private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate, private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate,
Function<Number, T> toConcreteNumber) { Function<Number, T> toConcreteNumber) {
saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0); saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0);
@ -2086,6 +2096,10 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
record EnumMapOwner(@Id Long id, String name, Map<Color, MapElement> map) { record EnumMapOwner(@Id Long id, String name, Map<Color, MapElement> map) {
} }
record WithOneToOne(@Id String id,@MappedCollection(idColumn = "renamed") Referenced referenced){}
record Referenced(@Id Long id) {
}
@Configuration @Configuration
@Import(TestConfiguration.class) @Import(TestConfiguration.class)

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

@ -30,6 +30,7 @@ import java.time.ZoneOffset;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.assertj.core.api.SoftAssertions; import org.assertj.core.api.SoftAssertions;
@ -39,8 +40,10 @@ import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.jdbc.core.mapping.JdbcValue; import org.springframework.data.jdbc.core.mapping.JdbcValue;
import org.springframework.data.jdbc.support.JdbcUtil; import org.springframework.data.jdbc.support.JdbcUtil;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.domain.RowDocument;
import org.springframework.data.util.TypeInformation; import org.springframework.data.util.TypeInformation;
/** /**
@ -139,6 +142,17 @@ public class MappingJdbcConverterUnitTests {
assertThat(typeFactory.arraySource).containsExactly(1, 2, 3, 4, 5); assertThat(typeFactory.arraySource).containsExactly(1, 2, 3, 4, 5);
} }
@Test // GH-1684
void accessesCorrectValuesForOneToOneRelationshipWithIdenticallyNamedIdProperties() {
RowDocument rowdocument = new RowDocument(Map.of("ID", "one", "REFERENCED_ID", 23));
WithOneToOne result = converter.readAndResolve(WithOneToOne.class, rowdocument);
assertThat(result).isEqualTo(new WithOneToOne("one", new Referenced(23L)));
}
private void checkConversionToTimestampAndBack(SoftAssertions softly, RelationalPersistentEntity<?> persistentEntity, private void checkConversionToTimestampAndBack(SoftAssertions softly, RelationalPersistentEntity<?> persistentEntity,
String propertyName, Object value) { String propertyName, Object value) {
@ -284,4 +298,10 @@ public class MappingJdbcConverterUnitTests {
return mock(Array.class); return mock(Array.class);
} }
} }
record WithOneToOne(@Id String id,@MappedCollection(idColumn = "renamed") Referenced referenced){}
record Referenced(@Id Long id) {
}
} }

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

@ -52,6 +52,10 @@ DROP TABLE AUTHOR;
DROP TABLE ENUM_MAP_OWNER; DROP TABLE ENUM_MAP_OWNER;
DROP TABLE REFERENCED;
DROP TABLE WITH_ONE_TO_ONE;
CREATE TABLE LEGO_SET CREATE TABLE LEGO_SET
( (
"id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, "id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
@ -429,3 +433,14 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
);

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

@ -386,3 +386,14 @@ CREATE TABLE ENUM_MAP_OWNER
ID SERIAL PRIMARY KEY, ID SERIAL PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
);

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

@ -387,3 +387,15 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
);

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

@ -360,3 +360,14 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT AUTO_INCREMENT PRIMARY KEY, ID BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
`renamed` VARCHAR(100),
ID BIGINT
);

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

@ -402,3 +402,18 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT IDENTITY PRIMARY KEY, ID BIGINT IDENTITY PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
DROP TABLE REFERENCED;
DROP TABLE WITH_ONE_TO_ONE;
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
);

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

@ -365,3 +365,15 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT AUTO_INCREMENT PRIMARY KEY, ID BIGINT AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
`renamed` VARCHAR(100),
ID BIGINT
);

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

@ -42,6 +42,9 @@ DROP TABLE AUTHOR CASCADE CONSTRAINTS PURGE;
DROP TABLE ENUM_MAP_OWNER CASCADE CONSTRAINTS PURGE; DROP TABLE ENUM_MAP_OWNER CASCADE CONSTRAINTS PURGE;
DROP TABLE REFERENCED CASCADE CONSTRAINTS PURGE;
DROP TABLE WITH_ONE_TO_ONE CASCADE CONSTRAINTS PURGE;
CREATE TABLE LEGO_SET CREATE TABLE LEGO_SET
( (
"id1" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, "id1" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY,
@ -410,3 +413,14 @@ CREATE TABLE ENUM_MAP_OWNER
ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, ID NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID NUMBER
);

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

@ -45,6 +45,9 @@ DROP TABLE AUTHOR;
DROP TABLE ENUM_MAP_OWNER; DROP TABLE ENUM_MAP_OWNER;
DROP TABLE REFERENCED;
DROP TABLE WITH_ONE_TO_ONE;
CREATE TABLE LEGO_SET CREATE TABLE LEGO_SET
( (
"id1" SERIAL PRIMARY KEY, "id1" SERIAL PRIMARY KEY,
@ -432,3 +435,14 @@ CREATE TABLE ENUM_MAP_OWNER
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
NAME VARCHAR(100) NAME VARCHAR(100)
); );
CREATE TABLE WITH_ONE_TO_ONE
(
ID VARCHAR(100)
);
CREATE TABLE REFERENCED
(
"renamed" VARCHAR(100),
ID BIGINT
);

Loading…
Cancel
Save