Skip to content

Commit 6fcff3e

Browse files
schlagi123mp911de
authored andcommitted
DATAJDBC-331 Introduce @MappedCollection annotation.
We now provide a @MappedCollection annotation as replacement for @column's keyColumn attribute. class Person { @MappedCollection(idColumn = "the_id", keyColumn = "the_key") private List<Integer> mappedList; } Original pull request: #117.
1 parent 1c0bd4f commit 6fcff3e

File tree

7 files changed

+98
-17
lines changed

7 files changed

+98
-17
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.data.mapping.PropertyHandler;
3232
import org.springframework.data.relational.core.mapping.BasicRelationalPersistentProperty;
3333
import org.springframework.data.relational.core.mapping.Column;
34+
import org.springframework.data.relational.core.mapping.MappedCollection;
3435
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3536
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
3637
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@@ -137,7 +138,7 @@ private static class DummyEntity {
137138
private final List<String> listField;
138139
private final UUID uuid;
139140

140-
@Column(value = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
141+
@MappedCollection(idColumn = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
141142

142143
// DATACMNS-106
143144
private @Column("dummy_name") String name;

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedWithCollectionIntegrationTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.data.jdbc.testing.TestConfiguration;
3333
import org.springframework.data.relational.core.mapping.Column;
3434
import org.springframework.data.relational.core.mapping.Embedded;
35+
import org.springframework.data.relational.core.mapping.MappedCollection;
3536
import org.springframework.data.repository.CrudRepository;
3637
import org.springframework.jdbc.core.JdbcTemplate;
3738
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@@ -254,7 +255,7 @@ private static class DummyEntity {
254255

255256
@Data
256257
private static class Embeddable {
257-
@Column(value = "id", keyColumn = "order_key")
258+
@MappedCollection(idColumn = "id", keyColumn = "order_key")
258259
List<DummyEntity2> list = new ArrayList<>();
259260

260261
String test;

spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import java.util.Date;
2222
import java.util.LinkedHashMap;
2323
import java.util.Map;
24+
import java.util.Objects;
2425
import java.util.Optional;
2526
import java.util.Set;
27+
import java.util.stream.Stream;
2628

2729
import org.springframework.data.mapping.Association;
2830
import org.springframework.data.mapping.PersistentEntity;
@@ -57,7 +59,8 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
5759

5860
private final RelationalMappingContext context;
5961
private final Lazy<Optional<String>> columnName;
60-
private final Lazy<Optional<String>> keyColumnName;
62+
private final Lazy<Optional<String>> collectionIdColumnName;
63+
private final Lazy<Optional<String>> collectionKeyColumnName;
6164
private final Lazy<Boolean> isEmbedded;
6265
private final Lazy<String> embeddedPrefix;
6366
private final Lazy<Class<?>> columnType = Lazy.of(this::doGetColumnType);
@@ -88,13 +91,37 @@ public BasicRelationalPersistentProperty(Property property, PersistentEntity<?,
8891
this.columnName = Lazy.of(() -> Optional.ofNullable( //
8992
findAnnotation(Column.class)) //
9093
.map(Column::value) //
91-
.filter(StringUtils::hasText) //
94+
.filter(StringUtils::hasText)//
9295
);
9396

94-
this.keyColumnName = Lazy.of(() -> Optional.ofNullable( //
95-
findAnnotation(Column.class)) //
96-
.map(Column::keyColumn) //
97-
.filter(StringUtils::hasText) //
97+
this.collectionIdColumnName = Lazy.of(() ->
98+
Stream.concat( //
99+
Stream.of( //
100+
findAnnotation(MappedCollection.class)) //
101+
.filter(Objects::nonNull) //
102+
.map(MappedCollection::idColumn), //
103+
Stream.of( //
104+
findAnnotation(Column.class)) //
105+
.filter(Objects::nonNull) //
106+
.map(Column::value) //
107+
)
108+
.filter(StringUtils::hasText)
109+
.findFirst()
110+
);
111+
112+
this.collectionKeyColumnName = Lazy.of(() ->
113+
Stream.concat( //
114+
Stream.of( //
115+
findAnnotation(MappedCollection.class)) //
116+
.filter(Objects::nonNull) //
117+
.map(MappedCollection::keyColumn), //
118+
Stream.of( //
119+
findAnnotation(Column.class)) //
120+
.filter(Objects::nonNull) //
121+
.map(Column::keyColumn) //
122+
)
123+
.filter(StringUtils::hasText)
124+
.findFirst()
98125
);
99126
}
100127

@@ -173,14 +200,14 @@ public RelationalPersistentEntity<?> getOwner() {
173200

174201
@Override
175202
public String getReverseColumnName() {
176-
return columnName.get().orElseGet(() -> context.getNamingStrategy().getReverseColumnName(this));
203+
return collectionIdColumnName.get().orElseGet(() -> context.getNamingStrategy().getReverseColumnName(this));
177204
}
178205

179206
@Override
180207
public String getKeyColumn() {
181208

182209
if (isQualified()) {
183-
return keyColumnName.get().orElseGet(() -> context.getNamingStrategy().getKeyColumn(this));
210+
return collectionKeyColumnName.get().orElseGet(() -> context.getNamingStrategy().getKeyColumn(this));
184211
} else {
185212
return null;
186213
}

spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/Column.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*
2727
* @author Kazuki Shimizu
2828
* @author Florian Lüdiger
29+
* @author Bastian Wilhelm
2930
*/
3031
@Retention(RetentionPolicy.RUNTIME)
3132
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@@ -39,6 +40,9 @@
3940

4041
/**
4142
* The column name for key columns of List or Map collections.
43+
*
44+
* @deprecated since 1.1, was used for collection mapping. Use {@link MappedCollection} instead of this.
4245
*/
46+
@Deprecated
4347
String keyColumn() default "";
4448
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.relational.core.mapping;
17+
18+
import java.lang.annotation.Documented;
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
/**
25+
* The annotation to configure the mapping from an collection in the database.
26+
*
27+
* @since 1.1
28+
* @author Bastian Wilhelm
29+
*/
30+
@Retention(RetentionPolicy.RUNTIME)
31+
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
32+
@Documented
33+
public @interface MappedCollection {
34+
35+
/**
36+
* The column name for id column in the corresponding relationship table.
37+
* If the default value (empty String) is used, the column name is resolved by the used
38+
* {@link NamingStrategy} method {@link NamingStrategy#getReverseColumnName(RelationalPersistentProperty)}
39+
*/
40+
String idColumn() default "";
41+
42+
/**
43+
* The column name for key columns of List or Map collections in the corresponding relationship table.
44+
* If the default value (empty String) is used, the column name is resolved by the used
45+
* {@link NamingStrategy} method {@link NamingStrategy#getKeyColumn(RelationalPersistentProperty)}
46+
*/
47+
String keyColumn() default "";
48+
}

spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ private static class DummyEntity {
182182
private final List<OtherEntity> listOfEntity;
183183
private final OtherEntity[] arrayOfEntity;
184184

185-
@Column(value = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
185+
@MappedCollection(idColumn = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
186186

187187
// DATACMNS-106
188188
private @Column("dummy_name") String name;

src/main/asciidoc/jdbc.adoc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ You can change this name by implementing `NamingStrategy.getReverseColumnName(Re
136136
* `Map<simple type, some entity>` is considered a qualified one-to-many relationship.
137137
The table of the referenced entity is expected to have two additional columns: One named the same as the table of the referencing entity for the foreign key and one with the same name and an additional `_key` suffix for the map key.
138138
You can change this behavior by implementing `NamingStrategy.getReverseColumnName(RelationalPersistentProperty property)` and `NamingStrategy.getKeyColumn(RelationalPersistentProperty property)`, respectively.
139-
Alternatively you may annotate the attribute with `@Column(value="your_column_name", keyColumn="your_key_column_name")`
139+
Alternatively you may annotate the attribute with `@MappedCollection(idColumn="your_column_name", keyColumn="your_key_column_name")`
140140

141141
* `List<some entity>` is mapped as a `Map<Integer, some entity>`.
142142

@@ -233,10 +233,10 @@ public class MyEntity {
233233
----
234234
====
235235

236-
The {javadoc-base}org/springframework/data/relational/core/mapping/Column.html[`@Column`] annotation can also be used on a reference type (one-to-one relationship) or on Sets, Lists, and Maps (one-to-many relationship)
236+
The {javadoc-base}org/springframework/data/relational/core/mapping/MappedCollection.html[`@MappedCollection`] annotation can be used on a reference type (one-to-one relationship) or on Sets, Lists, and Maps (one-to-many relationship)
237237
On all these types the `value` element of the annotation is used to provide a custom name for the foreign key column referencing the id column in the other table.
238238
In the following example the corresponding table for the `MySubEntity` class has a name column, and the id column of the `MyEntity` id for relationship reasons.
239-
The name of this `MySubEntity` class's id column can also be customized with the `value` element of the {javadoc-base}org/springframework/data/relational/core/mapping/Column.html[`@Column`] annotation:
239+
The name of this `MySubEntity` class's id column can also be customized with the `idColumn` element of the {javadoc-base}org/springframework/data/relational/core/mapping/MappedCollection.html[`@MappedCollection`] annotation:
240240

241241
====
242242
[source, java]
@@ -245,7 +245,7 @@ public class MyEntity {
245245
@Id
246246
Integer id;
247247
248-
@Column("CUSTOM_COLUMN_NAME")
248+
@MappedCollection(idColumn = "CUSTOM_COLUMN_NAME")
249249
Set<MySubEntity> name;
250250
}
251251
@@ -256,7 +256,7 @@ public class MySubEntity {
256256
====
257257

258258
When using `List` and `Map` you must have an additional column for the position of a dataset in the `List` or the key value of the entity in the `Map`.
259-
This additional column name may be customized with the `keyColumn` Element of the {javadoc-base}org/springframework/data/relational/core/mapping/Column.html[`@Column`] annotation:
259+
This additional column name may be customized with the `keyColumn` Element of the {javadoc-base}org/springframework/data/relational/core/mapping/MappedCollection.html[`@MappedCollection`] annotation:
260260

261261
====
262262
[source, java]
@@ -265,7 +265,7 @@ public class MyEntity {
265265
@Id
266266
Integer id;
267267
268-
@Column(value = "CUSTOM_COLUMN_NAME", keyColumn = "CUSTOM_KEY_COLUMN_NAME")
268+
@MappedCollection(idColumn = "CUSTOM_COLUMN_NAME", keyColumn = "CUSTOM_KEY_COLUMN_NAME")
269269
List<MySubEntity> name;
270270
}
271271

0 commit comments

Comments
 (0)