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 254fc3076..73f5d85b5 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 @@ -245,7 +245,7 @@ class JdbcAggregateChangeExecutionContext { 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 7c20d43b0..09a8d3142 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,7 +23,9 @@ import java.util.Map; import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension; import org.springframework.data.relational.core.sql.IdentifierProcessing; import org.springframework.data.relational.core.sql.SqlIdentifier; +import org.springframework.data.util.TypeInformation; import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.JdbcUtils; /** * A {@link RowMapper} that maps a row to a {@link Map.Entry} so an {@link Iterable} of those can be converted to a @@ -50,8 +52,11 @@ 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)); + Object key = new ResultSetAccessor(rs).getObject(keyColumn.getReference()); + Class qualifierColumnType = path.getRequiredPersistentPropertyPath().getLeafProperty().getQualifierColumnType(); + Object convertedKey = converter.readValue(key, TypeInformation.of(qualifierColumnType)); + + return new HashMap.SimpleEntry<>(convertedKey, mapEntity(rs, key)); } private T mapEntity(ResultSet resultSet, Object key) { diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java index f0cfa10ee..7b7959a9e 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java @@ -1095,6 +1095,16 @@ class JdbcAggregateTemplateIntegrationTests { assertThat(template.findById(entity.id, EnumArrayOwner.class).digits).isEqualTo(new Color[]{Color.BLUE}); } + @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); @@ -1548,6 +1558,12 @@ class JdbcAggregateTemplateIntegrationTests { String insertOnly; } + record EnumMapOwner(@Id Long id, String name, Map map) { + } + + record MapElement(String name) { + } + @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 8ad4fda2d..2b6f0880e 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 @@ -41,14 +41,17 @@ DROP TABLE WITH_ID_ONLY; DROP TABLE WITH_INSERT_ONLY; +DROP TABLE MAP_ELEMENT; +DROP TABLE ENUM_MAP_OWNER; + CREATE TABLE LEGO_SET ( - "id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, - NAME VARCHAR(30) + "id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + NAME VARCHAR(30) ); CREATE TABLE MANUAL ( - "id2" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + "id2" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, LEGO_SET BIGINT, "alternative" BIGINT, CONTENT VARCHAR(2000) @@ -358,11 +361,26 @@ CREATE TABLE WITH_LOCAL_DATE_TIME CREATE TABLE WITH_ID_ONLY ( - ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY ); CREATE TABLE WITH_INSERT_ONLY ( - ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, - INSERT_ONLY VARCHAR(100) -); \ No newline at end of file + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + INSERT_ONLY VARCHAR(100) +); + +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) +); + +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-h2.sql b/spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql index a0aff08ce..5dfcd8f1c 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 @@ -330,6 +330,21 @@ CREATE TABLE WITH_ID_ONLY CREATE TABLE WITH_INSERT_ONLY ( - ID SERIAL PRIMARY KEY, + ID SERIAL PRIMARY KEY, INSERT_ONLY VARCHAR(100) -); \ No newline at end of file +); + +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) +); + +CREATE TABLE ENUM_MAP_OWNER +( + ID SERIAL PRIMARY KEY, + NAME VARCHAR(100) +); 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 4dd1294ab..31f7ebe33 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 @@ -327,11 +327,26 @@ CREATE TABLE WITH_LOCAL_DATE_TIME CREATE TABLE WITH_INSERT_ONLY ( - ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, INSERT_ONLY VARCHAR(100) ); CREATE TABLE WITH_ID_ONLY ( ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY -) \ No newline at end of file +); + +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) +); + +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 4dd82b900..c29761aff 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 @@ -300,11 +300,26 @@ CREATE TABLE WITH_LOCAL_DATE_TIME CREATE TABLE WITH_ID_ONLY ( - ID BIGINT AUTO_INCREMENT PRIMARY KEY + ID BIGINT AUTO_INCREMENT PRIMARY KEY ); CREATE TABLE WITH_INSERT_ONLY ( - ID BIGINT AUTO_INCREMENT PRIMARY KEY, - INSERT_ONLY VARCHAR(100) -); \ No newline at end of file + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + INSERT_ONLY VARCHAR(100) +); + +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) +); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + NAME VARCHAR(100) +); 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 880528cdb..c1bdd4f84 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 @@ -337,6 +337,23 @@ DROP TABLE IF EXISTS WITH_INSERT_ONLY; CREATE TABLE WITH_INSERT_ONLY ( - ID BIGINT IDENTITY PRIMARY KEY, - INSERT_ONLY VARCHAR(100) -); \ No newline at end of file + ID BIGINT IDENTITY PRIMARY KEY, + INSERT_ONLY VARCHAR(100) +); + +DROP TABLE MAP_ELEMENT; +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) +); + +DROP TABLE ENUM_MAP_OWNER; +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT IDENTITY PRIMARY KEY, + NAME VARCHAR(100) +); 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 6808c8a91..2a7183c19 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 @@ -305,11 +305,26 @@ CREATE TABLE WITH_LOCAL_DATE_TIME CREATE TABLE WITH_ID_ONLY ( - ID BIGINT AUTO_INCREMENT PRIMARY KEY + ID BIGINT AUTO_INCREMENT PRIMARY KEY ); CREATE TABLE WITH_INSERT_ONLY ( - ID BIGINT AUTO_INCREMENT PRIMARY KEY, - INSERT_ONLY VARCHAR(100) -); \ No newline at end of file + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + INSERT_ONLY VARCHAR(100) +); + +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) +); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + NAME VARCHAR(100) +); 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 084e5db46..0463b94e7 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 @@ -31,14 +31,17 @@ DROP TABLE WITH_LOCAL_DATE_TIME CASCADE CONSTRAINTS PURGE; DROP TABLE WITH_ID_ONLY CASCADE CONSTRAINTS PURGE; DROP TABLE WITH_INSERT_ONLY CASCADE CONSTRAINTS PURGE; +DROP TABLE MAP_ELEMENT 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, - NAME VARCHAR(30) + NAME VARCHAR(30) ); CREATE TABLE MANUAL ( - "id2" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, + "id2" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, LEGO_SET NUMBER, ALTERNATIVE NUMBER, CONTENT VARCHAR(2000) @@ -338,12 +341,27 @@ CREATE TABLE WITH_LOCAL_DATE_TIME CREATE TABLE WITH_ID_ONLY ( - ID NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY + ID NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY ); CREATE TABLE WITH_INSERT_ONLY ( - ID NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, - INSERT_ONLY VARCHAR(100) -); \ No newline at end of file + ID NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY, + INSERT_ONLY VARCHAR(100) +); + +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) +); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + NAME VARCHAR(100) +); 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 ed1fb9662..07838b535 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 @@ -15,6 +15,9 @@ DROP TABLE WITH_READ_ONLY; DROP TABLE WITH_ID_ONLY; DROP TABLE WITH_INSERT_ONLY; +DROP TABLE MAP_ELEMENT; +DROP TABLE ENUM_MAP_OWNER; + CREATE TABLE LEGO_SET ( "id1" SERIAL PRIMARY KEY, @@ -346,6 +349,21 @@ CREATE TABLE WITH_ID_ONLY CREATE TABLE WITH_INSERT_ONLY ( - ID SERIAL PRIMARY KEY, + ID SERIAL PRIMARY KEY, INSERT_ONLY VARCHAR(100) -); \ No newline at end of file +); + +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) +); + +CREATE TABLE ENUM_MAP_OWNER +( + ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, + NAME VARCHAR(100) +);