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.
This commit is contained in:
committed by
Mark Paluch
parent
1c0bd4fdb8
commit
6fcff3ea80
@@ -31,6 +31,7 @@ import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.relational.core.mapping.BasicRelationalPersistentProperty;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.MappedCollection;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
|
||||
@@ -137,7 +138,7 @@ public class BasicJdbcPersistentPropertyUnitTests {
|
||||
private final List<String> listField;
|
||||
private final UUID uuid;
|
||||
|
||||
@Column(value = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
|
||||
@MappedCollection(idColumn = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
|
||||
|
||||
// DATACMNS-106
|
||||
private @Column("dummy_name") String name;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.Embedded;
|
||||
import org.springframework.data.relational.core.mapping.MappedCollection;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
@@ -254,7 +255,7 @@ public class JdbcRepositoryEmbeddedWithCollectionIntegrationTests {
|
||||
|
||||
@Data
|
||||
private static class Embeddable {
|
||||
@Column(value = "id", keyColumn = "order_key")
|
||||
@MappedCollection(idColumn = "id", keyColumn = "order_key")
|
||||
List<DummyEntity2> list = new ArrayList<>();
|
||||
|
||||
String test;
|
||||
|
||||
@@ -21,8 +21,10 @@ import java.time.temporal.Temporal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
@@ -57,7 +59,8 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
|
||||
private final RelationalMappingContext context;
|
||||
private final Lazy<Optional<String>> columnName;
|
||||
private final Lazy<Optional<String>> keyColumnName;
|
||||
private final Lazy<Optional<String>> collectionIdColumnName;
|
||||
private final Lazy<Optional<String>> collectionKeyColumnName;
|
||||
private final Lazy<Boolean> isEmbedded;
|
||||
private final Lazy<String> embeddedPrefix;
|
||||
private final Lazy<Class<?>> columnType = Lazy.of(this::doGetColumnType);
|
||||
@@ -88,13 +91,37 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
this.columnName = Lazy.of(() -> Optional.ofNullable( //
|
||||
findAnnotation(Column.class)) //
|
||||
.map(Column::value) //
|
||||
.filter(StringUtils::hasText) //
|
||||
.filter(StringUtils::hasText)//
|
||||
);
|
||||
|
||||
this.keyColumnName = Lazy.of(() -> Optional.ofNullable( //
|
||||
findAnnotation(Column.class)) //
|
||||
.map(Column::keyColumn) //
|
||||
.filter(StringUtils::hasText) //
|
||||
this.collectionIdColumnName = Lazy.of(() ->
|
||||
Stream.concat( //
|
||||
Stream.of( //
|
||||
findAnnotation(MappedCollection.class)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.map(MappedCollection::idColumn), //
|
||||
Stream.of( //
|
||||
findAnnotation(Column.class)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.map(Column::value) //
|
||||
)
|
||||
.filter(StringUtils::hasText)
|
||||
.findFirst()
|
||||
);
|
||||
|
||||
this.collectionKeyColumnName = Lazy.of(() ->
|
||||
Stream.concat( //
|
||||
Stream.of( //
|
||||
findAnnotation(MappedCollection.class)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.map(MappedCollection::keyColumn), //
|
||||
Stream.of( //
|
||||
findAnnotation(Column.class)) //
|
||||
.filter(Objects::nonNull) //
|
||||
.map(Column::keyColumn) //
|
||||
)
|
||||
.filter(StringUtils::hasText)
|
||||
.findFirst()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -173,14 +200,14 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
|
||||
@Override
|
||||
public String getReverseColumnName() {
|
||||
return columnName.get().orElseGet(() -> context.getNamingStrategy().getReverseColumnName(this));
|
||||
return collectionIdColumnName.get().orElseGet(() -> context.getNamingStrategy().getReverseColumnName(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyColumn() {
|
||||
|
||||
if (isQualified()) {
|
||||
return keyColumnName.get().orElseGet(() -> context.getNamingStrategy().getKeyColumn(this));
|
||||
return collectionKeyColumnName.get().orElseGet(() -> context.getNamingStrategy().getKeyColumn(this));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Kazuki Shimizu
|
||||
* @author Florian Lüdiger
|
||||
* @author Bastian Wilhelm
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@@ -39,6 +40,9 @@ public @interface Column {
|
||||
|
||||
/**
|
||||
* The column name for key columns of List or Map collections.
|
||||
*
|
||||
* @deprecated since 1.1, was used for collection mapping. Use {@link MappedCollection} instead of this.
|
||||
*/
|
||||
@Deprecated
|
||||
String keyColumn() default "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The annotation to configure the mapping from an collection in the database.
|
||||
*
|
||||
* @since 1.1
|
||||
* @author Bastian Wilhelm
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Documented
|
||||
public @interface MappedCollection {
|
||||
|
||||
/**
|
||||
* The column name for id column in the corresponding relationship table.
|
||||
* If the default value (empty String) is used, the column name is resolved by the used
|
||||
* {@link NamingStrategy} method {@link NamingStrategy#getReverseColumnName(RelationalPersistentProperty)}
|
||||
*/
|
||||
String idColumn() default "";
|
||||
|
||||
/**
|
||||
* The column name for key columns of List or Map collections in the corresponding relationship table.
|
||||
* If the default value (empty String) is used, the column name is resolved by the used
|
||||
* {@link NamingStrategy} method {@link NamingStrategy#getKeyColumn(RelationalPersistentProperty)}
|
||||
*/
|
||||
String keyColumn() default "";
|
||||
}
|
||||
@@ -182,7 +182,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
private final List<OtherEntity> listOfEntity;
|
||||
private final OtherEntity[] arrayOfEntity;
|
||||
|
||||
@Column(value = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
|
||||
@MappedCollection(idColumn = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
|
||||
|
||||
// DATACMNS-106
|
||||
private @Column("dummy_name") String name;
|
||||
|
||||
@@ -136,7 +136,7 @@ You can change this name by implementing `NamingStrategy.getReverseColumnName(Re
|
||||
* `Map<simple type, some entity>` is considered a qualified one-to-many relationship.
|
||||
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.
|
||||
You can change this behavior by implementing `NamingStrategy.getReverseColumnName(RelationalPersistentProperty property)` and `NamingStrategy.getKeyColumn(RelationalPersistentProperty property)`, respectively.
|
||||
Alternatively you may annotate the attribute with `@Column(value="your_column_name", keyColumn="your_key_column_name")`
|
||||
Alternatively you may annotate the attribute with `@MappedCollection(idColumn="your_column_name", keyColumn="your_key_column_name")`
|
||||
|
||||
* `List<some entity>` is mapped as a `Map<Integer, some entity>`.
|
||||
|
||||
@@ -233,10 +233,10 @@ public class MyEntity {
|
||||
----
|
||||
====
|
||||
|
||||
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)
|
||||
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)
|
||||
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.
|
||||
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.
|
||||
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:
|
||||
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:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
@@ -245,7 +245,7 @@ public class MyEntity {
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@Column("CUSTOM_COLUMN_NAME")
|
||||
@MappedCollection(idColumn = "CUSTOM_COLUMN_NAME")
|
||||
Set<MySubEntity> name;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ public class MySubEntity {
|
||||
====
|
||||
|
||||
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`.
|
||||
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:
|
||||
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:
|
||||
|
||||
====
|
||||
[source, java]
|
||||
@@ -265,7 +265,7 @@ public class MyEntity {
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@Column(value = "CUSTOM_COLUMN_NAME", keyColumn = "CUSTOM_KEY_COLUMN_NAME")
|
||||
@MappedCollection(idColumn = "CUSTOM_COLUMN_NAME", keyColumn = "CUSTOM_KEY_COLUMN_NAME")
|
||||
List<MySubEntity> name;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user