|
23 | 23 | import static org.springframework.data.jdbc.testing.TestDatabaseFeatures.Feature.*;
|
24 | 24 | import static org.springframework.test.context.TestExecutionListeners.MergeMode.*;
|
25 | 25 |
|
| 26 | +import java.sql.ResultSet; |
| 27 | +import java.sql.SQLException; |
26 | 28 | import java.time.LocalDateTime;
|
27 | 29 | import java.util.ArrayList;
|
28 | 30 | import java.util.Collections;
|
|
37 | 39 | import java.util.stream.IntStream;
|
38 | 40 |
|
39 | 41 | import org.assertj.core.api.SoftAssertions;
|
| 42 | +import org.junit.jupiter.api.Disabled; |
40 | 43 | import org.junit.jupiter.api.Test;
|
41 | 44 | import org.junit.jupiter.api.extension.ExtendWith;
|
42 | 45 | import org.springframework.beans.factory.annotation.Autowired;
|
43 | 46 | import org.springframework.context.ApplicationEventPublisher;
|
44 | 47 | import org.springframework.context.annotation.Bean;
|
45 | 48 | import org.springframework.context.annotation.Configuration;
|
46 | 49 | import org.springframework.context.annotation.Import;
|
| 50 | +import org.springframework.dao.DataAccessException; |
47 | 51 | import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
|
48 | 52 | import org.springframework.dao.OptimisticLockingFailureException;
|
49 | 53 | import org.springframework.data.annotation.Id;
|
|
67 | 71 | import org.springframework.data.relational.core.mapping.MappedCollection;
|
68 | 72 | import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
69 | 73 | import org.springframework.data.relational.core.mapping.Table;
|
| 74 | +import org.springframework.jdbc.core.ResultSetExtractor; |
70 | 75 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
71 | 76 | import org.springframework.test.context.ActiveProfiles;
|
72 | 77 | import org.springframework.test.context.ContextConfiguration;
|
@@ -98,6 +103,7 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
|
98 | 103 | @Autowired JdbcAggregateOperations template;
|
99 | 104 | @Autowired NamedParameterJdbcOperations jdbcTemplate;
|
100 | 105 | @Autowired RelationalMappingContext mappingContext;
|
| 106 | + @Autowired NamedParameterJdbcOperations jdbc; |
101 | 107 |
|
102 | 108 | LegoSet legoSet = createLegoSet("Star Destroyer");
|
103 | 109 |
|
@@ -1149,6 +1155,115 @@ void readEnumArray() {
|
1149 | 1155 | assertThat(template.findById(entity.id, EnumArrayOwner.class).digits).isEqualTo(new Color[] { Color.BLUE });
|
1150 | 1156 | }
|
1151 | 1157 |
|
| 1158 | + @Test // GH-1448 |
| 1159 | + void multipleCollections() { |
| 1160 | + |
| 1161 | + MultipleCollections aggregate = new MultipleCollections(); |
| 1162 | + aggregate.name = "aggregate"; |
| 1163 | + |
| 1164 | + aggregate.listElements.add(new ListElement("one")); |
| 1165 | + aggregate.listElements.add(new ListElement("two")); |
| 1166 | + aggregate.listElements.add(new ListElement("three")); |
| 1167 | + |
| 1168 | + aggregate.setElements.add(new SetElement("one")); |
| 1169 | + aggregate.setElements.add(new SetElement("two")); |
| 1170 | + |
| 1171 | + aggregate.mapElements.put("alpha", new MapElement("one")); |
| 1172 | + aggregate.mapElements.put("beta", new MapElement("two")); |
| 1173 | + aggregate.mapElements.put("gamma", new MapElement("three")); |
| 1174 | + aggregate.mapElements.put("delta", new MapElement("four")); |
| 1175 | + |
| 1176 | + template.save(aggregate); |
| 1177 | + |
| 1178 | + MultipleCollections reloaded = template.findById(aggregate.id, MultipleCollections.class); |
| 1179 | + |
| 1180 | + assertSoftly(softly -> { |
| 1181 | + |
| 1182 | + softly.assertThat(reloaded.name).isEqualTo(aggregate.name); |
| 1183 | + |
| 1184 | + softly.assertThat(reloaded.listElements).containsExactly(aggregate.listElements.get(0), |
| 1185 | + aggregate.listElements.get(1), aggregate.listElements.get(2)); |
| 1186 | + |
| 1187 | + softly.assertThat(reloaded.setElements) |
| 1188 | + .containsExactlyInAnyOrder(aggregate.setElements.toArray(new SetElement[0])); |
| 1189 | + |
| 1190 | + softly.assertThat(reloaded.mapElements.get("alpha")).isEqualTo(new MapElement("one")); |
| 1191 | + softly.assertThat(reloaded.mapElements.get("beta")).isEqualTo(new MapElement("two")); |
| 1192 | + softly.assertThat(reloaded.mapElements.get("gamma")).isEqualTo(new MapElement("three")); |
| 1193 | + softly.assertThat(reloaded.mapElements.get("delta")).isEqualTo(new MapElement("four")); |
| 1194 | + }); |
| 1195 | + } |
| 1196 | + |
| 1197 | + @Test // GH-1448 |
| 1198 | + void multipleCollectionsWithEmptySet() { |
| 1199 | + |
| 1200 | + MultipleCollections aggregate = new MultipleCollections(); |
| 1201 | + aggregate.name = "aggregate"; |
| 1202 | + |
| 1203 | + aggregate.listElements.add(new ListElement("one")); |
| 1204 | + aggregate.listElements.add(new ListElement("two")); |
| 1205 | + aggregate.listElements.add(new ListElement("three")); |
| 1206 | + |
| 1207 | + aggregate.mapElements.put("alpha", new MapElement("one")); |
| 1208 | + aggregate.mapElements.put("beta", new MapElement("two")); |
| 1209 | + aggregate.mapElements.put("gamma", new MapElement("three")); |
| 1210 | + aggregate.mapElements.put("delta", new MapElement("four")); |
| 1211 | + |
| 1212 | + template.save(aggregate); |
| 1213 | + |
| 1214 | + MultipleCollections reloaded = template.findById(aggregate.id, MultipleCollections.class); |
| 1215 | + |
| 1216 | + assertSoftly(softly -> { |
| 1217 | + |
| 1218 | + softly.assertThat(reloaded.name).isEqualTo(aggregate.name); |
| 1219 | + |
| 1220 | + softly.assertThat(reloaded.listElements).containsExactly(aggregate.listElements.get(0), |
| 1221 | + aggregate.listElements.get(1), aggregate.listElements.get(2)); |
| 1222 | + |
| 1223 | + softly.assertThat(reloaded.setElements) |
| 1224 | + .containsExactlyInAnyOrder(aggregate.setElements.toArray(new SetElement[0])); |
| 1225 | + |
| 1226 | + softly.assertThat(reloaded.mapElements.get("alpha")).isEqualTo(new MapElement("one")); |
| 1227 | + softly.assertThat(reloaded.mapElements.get("beta")).isEqualTo(new MapElement("two")); |
| 1228 | + softly.assertThat(reloaded.mapElements.get("gamma")).isEqualTo(new MapElement("three")); |
| 1229 | + softly.assertThat(reloaded.mapElements.get("delta")).isEqualTo(new MapElement("four")); |
| 1230 | + }); |
| 1231 | + } |
| 1232 | + |
| 1233 | + @Test // GH-1448 |
| 1234 | + void multipleCollectionsWithEmptyList() { |
| 1235 | + |
| 1236 | + MultipleCollections aggregate = new MultipleCollections(); |
| 1237 | + aggregate.name = "aggregate"; |
| 1238 | + |
| 1239 | + aggregate.setElements.add(new SetElement("one")); |
| 1240 | + aggregate.setElements.add(new SetElement("two")); |
| 1241 | + |
| 1242 | + aggregate.mapElements.put("alpha", new MapElement("one")); |
| 1243 | + aggregate.mapElements.put("beta", new MapElement("two")); |
| 1244 | + aggregate.mapElements.put("gamma", new MapElement("three")); |
| 1245 | + aggregate.mapElements.put("delta", new MapElement("four")); |
| 1246 | + |
| 1247 | + template.save(aggregate); |
| 1248 | + |
| 1249 | + MultipleCollections reloaded = template.findById(aggregate.id, MultipleCollections.class); |
| 1250 | + |
| 1251 | + assertSoftly(softly -> { |
| 1252 | + |
| 1253 | + softly.assertThat(reloaded.name).isEqualTo(aggregate.name); |
| 1254 | + |
| 1255 | + softly.assertThat(reloaded.listElements).containsExactly(); |
| 1256 | + |
| 1257 | + softly.assertThat(reloaded.setElements) |
| 1258 | + .containsExactlyInAnyOrder(aggregate.setElements.toArray(new SetElement[0])); |
| 1259 | + |
| 1260 | + softly.assertThat(reloaded.mapElements.get("alpha")).isEqualTo(new MapElement("one")); |
| 1261 | + softly.assertThat(reloaded.mapElements.get("beta")).isEqualTo(new MapElement("two")); |
| 1262 | + softly.assertThat(reloaded.mapElements.get("gamma")).isEqualTo(new MapElement("three")); |
| 1263 | + softly.assertThat(reloaded.mapElements.get("delta")).isEqualTo(new MapElement("four")); |
| 1264 | + }); |
| 1265 | + } |
| 1266 | + |
1152 | 1267 | private <T extends Number> void saveAndUpdateAggregateWithVersion(VersionedAggregate aggregate,
|
1153 | 1268 | Function<Number, T> toConcreteNumber) {
|
1154 | 1269 | saveAndUpdateAggregateWithVersion(aggregate, toConcreteNumber, 0);
|
@@ -1858,6 +1973,24 @@ static class WithInsertOnly {
|
1858 | 1973 | @InsertOnlyProperty String insertOnly;
|
1859 | 1974 | }
|
1860 | 1975 |
|
| 1976 | + @Table |
| 1977 | + static class MultipleCollections { |
| 1978 | + @Id Long id; |
| 1979 | + String name; |
| 1980 | + List<ListElement> listElements = new ArrayList<>(); |
| 1981 | + Set<SetElement> setElements = new HashSet<>(); |
| 1982 | + Map<String, MapElement> mapElements = new HashMap<>(); |
| 1983 | + } |
| 1984 | + |
| 1985 | + record ListElement(String name) { |
| 1986 | + } |
| 1987 | + |
| 1988 | + record SetElement(String name) { |
| 1989 | + } |
| 1990 | + |
| 1991 | + record MapElement(String name) { |
| 1992 | + } |
| 1993 | + |
1861 | 1994 | @Configuration
|
1862 | 1995 | @Import(TestConfiguration.class)
|
1863 | 1996 | static class Config {
|
|
0 commit comments