From f7c75598194025ad9849e1973e7fc9995c630bf0 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Tue, 14 Nov 2023 11:08:34 +0100 Subject: [PATCH 1/2] 1656-enum-as-map-key - Prepare branch --- pom.xml | 2 +- spring-data-jdbc-distribution/pom.xml | 2 +- spring-data-jdbc/pom.xml | 4 ++-- spring-data-r2dbc/pom.xml | 4 ++-- spring-data-relational/pom.xml | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index d9ee91c910..cee6f52efa 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-relational-parent - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT pom Spring Data Relational Parent diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml index 271486f02a..1b928da6d6 100644 --- a/spring-data-jdbc-distribution/pom.xml +++ b/spring-data-jdbc-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT ../pom.xml diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml index 2ac75e7993..65ad60abb6 100644 --- a/spring-data-jdbc/pom.xml +++ b/spring-data-jdbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-jdbc - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT diff --git a/spring-data-r2dbc/pom.xml b/spring-data-r2dbc/pom.xml index d65f06a082..46d128590d 100644 --- a/spring-data-r2dbc/pom.xml +++ b/spring-data-r2dbc/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-r2dbc - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT Spring Data R2DBC Spring Data module for R2DBC @@ -15,7 +15,7 @@ org.springframework.data spring-data-relational-parent - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml index 74f350faa8..9bf89bbafb 100644 --- a/spring-data-relational/pom.xml +++ b/spring-data-relational/pom.xml @@ -6,7 +6,7 @@ 4.0.0 spring-data-relational - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT Spring Data Relational Spring Data Relational support @@ -14,7 +14,7 @@ org.springframework.data spring-data-relational-parent - 3.2.0-SNAPSHOT + 3.2.0-1656-enum-as-map-key-SNAPSHOT From 9f679a655809b91c83eff8c39097d22853f34078 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Wed, 15 Nov 2023 09:32:38 +0100 Subject: [PATCH 2/2] Convert key of maps. Keys of maps now get properly converted. Among others this enables the use of enums as keys. Closes #1656 --- .../JdbcAggregateChangeExecutionContext.java | 2 +- .../jdbc/core/convert/MapEntityRowMapper.java | 16 +++++++++++----- ...actJdbcAggregateTemplateIntegrationTests.java | 14 ++++++++++++++ ...JdbcAggregateTemplateIntegrationTests-db2.sql | 10 ++++++++++ .../JdbcAggregateTemplateIntegrationTests-h2.sql | 8 ++++++++ ...dbcAggregateTemplateIntegrationTests-hsql.sql | 8 ++++++++ ...AggregateTemplateIntegrationTests-mariadb.sql | 8 ++++++++ ...bcAggregateTemplateIntegrationTests-mssql.sql | 9 +++++++++ ...bcAggregateTemplateIntegrationTests-mysql.sql | 8 ++++++++ ...cAggregateTemplateIntegrationTests-oracle.sql | 10 ++++++++++ ...ggregateTemplateIntegrationTests-postgres.sql | 10 ++++++++++ 11 files changed, 97 insertions(+), 6 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java index 8c37babdd0..15c2326adf 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateChangeExecutionContext.java @@ -241,7 +241,7 @@ private Object getIdFrom(DbAction.WithEntity idOwningAction) { RelationalPersistentEntity persistentEntity = getRequiredPersistentEntity(idOwningAction.getEntityType()); Object identifier = persistentEntity.getIdentifierAccessor(idOwningAction.getEntity()).getIdentifier(); - Assert.state(identifier != null, "Couldn't obtain a required id value"); + Assert.state(identifier != null,() -> "Couldn't obtain a required id value for " + persistentEntity); return identifier; } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MapEntityRowMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MapEntityRowMapper.java index 05430670eb..79b219bed1 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MapEntityRowMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/MapEntityRowMapper.java @@ -23,6 +23,7 @@ import org.springframework.data.relational.core.mapping.AggregatePath; import org.springframework.data.relational.core.sql.SqlIdentifier; import org.springframework.data.relational.domain.RowDocument; +import org.springframework.data.util.TypeInformation; import org.springframework.jdbc.core.RowMapper; /** @@ -51,15 +52,20 @@ class MapEntityRowMapper implements RowMapper> { @Override public Map.Entry mapRow(ResultSet rs, int rowNum) throws SQLException { - Object key = rs.getObject(keyColumn.getReference()); - return new HashMap.SimpleEntry<>(key, mapEntity(rs, key)); + RowDocument document = RowDocumentResultSetExtractor.toRowDocument(rs); + + Object key = document.get(keyColumn.getReference()); + + Class qualifierColumnType = path.getRequiredLeafProperty().getQualifierColumnType(); + Object convertedKey = converter.readValue(key, TypeInformation.of(qualifierColumnType)); + + return new HashMap.SimpleEntry<>(convertedKey, mapEntity(document, key)); } @SuppressWarnings("unchecked") - private T mapEntity(ResultSet resultSet, Object key) throws SQLException { + private T mapEntity(RowDocument document, Object key) { - RowDocument document = RowDocumentResultSetExtractor.toRowDocument(resultSet); - return (T) converter.readAndResolve(path.getLeafEntity().getType(), document, + return (T) converter.readAndResolve(path.getRequiredLeafEntity().getType(), document, identifier.withPart(keyColumn, key, Object.class)); } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java index e20b0a9858..b823314b6e 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java @@ -1278,6 +1278,16 @@ void recordOfSet() { assertThat(authors).containsExactly(tolkien); } + @Test // GH-1656 + void mapWithEnumKey() { + + EnumMapOwner enumMapOwner = template.save(new EnumMapOwner(null, "OwnerName", Map.of(Color.BLUE, new MapElement("Element")))); + + Iterable enumMapOwners = template.findAll(EnumMapOwner.class); + + assertThat(enumMapOwners).containsExactly(enumMapOwner); + } + private void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate, Function toConcreteNumber) { saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0); @@ -2096,6 +2106,10 @@ record Book(String name) { } + record EnumMapOwner(@Id Long id, String name, Map map) { + } + + @Configuration @Import(TestConfiguration.class) static class Config { diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql index e03527af81..f548340523 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql @@ -50,6 +50,8 @@ DROP TABLE SET_ELEMENT; DROP TABLE BOOK; DROP TABLE AUTHOR; +DROP TABLE ENUM_MAP_OWNER; + CREATE TABLE LEGO_SET ( "id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, @@ -406,6 +408,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -419,3 +423,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql index 9f25599976..982b9e3163 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql @@ -365,6 +365,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -378,3 +380,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID SERIAL PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql index 80b2f8d10f..3ae51989a5 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql @@ -366,6 +366,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -379,3 +381,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + NAME VARCHAR(100) +); diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql index 677bd0d136..5e318e222f 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql @@ -339,6 +339,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -352,3 +354,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql index bfb37923f2..8323608b80 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql @@ -377,6 +377,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -393,3 +395,10 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +DROP TABLE ENUM_MAP_OWNER; +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT IDENTITY PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql index 5d65e73004..a6989938c5 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql @@ -344,6 +344,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -357,3 +359,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql index 0581608a03..d2f6aec658 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql @@ -40,6 +40,8 @@ DROP TABLE SET_ELEMENT CASCADE CONSTRAINTS PURGE; DROP TABLE BOOK CASCADE CONSTRAINTS PURGE; DROP TABLE AUTHOR CASCADE CONSTRAINTS PURGE; +DROP TABLE ENUM_MAP_OWNER CASCADE CONSTRAINTS PURGE; + CREATE TABLE LEGO_SET ( "id1" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, @@ -387,6 +389,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS NUMBER, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -400,3 +404,9 @@ CREATE TABLE BOOK AUTHOR NUMBER, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file diff --git a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql index df4fe5a7c8..72b88cddfd 100644 --- a/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql +++ b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql @@ -43,6 +43,8 @@ DROP TABLE SET_ELEMENT; DROP TABLE BOOK; DROP TABLE AUTHOR; +DROP TABLE ENUM_MAP_OWNER; + CREATE TABLE LEGO_SET ( "id1" SERIAL PRIMARY KEY, @@ -409,6 +411,8 @@ CREATE TABLE MAP_ELEMENT ( MULTIPLE_COLLECTIONS BIGINT, MULTIPLE_COLLECTIONS_KEY VARCHAR(10), + ENUM_MAP_OWNER BIGINT, + ENUM_MAP_OWNER_KEY VARCHAR(10), NAME VARCHAR(100) ); @@ -422,3 +426,9 @@ CREATE TABLE BOOK AUTHOR BIGINT, NAME VARCHAR(100) ); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + NAME VARCHAR(100) +); \ No newline at end of file