Skip to content

DATAJDBC-331 #117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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;
Expand Down Expand Up @@ -137,7 +138,7 @@ private static class DummyEntity {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
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;
Expand Down Expand Up @@ -254,7 +255,7 @@ private static class DummyEntity {

@Data
private static class Embeddable {
@Column(value = "id", keyColumn = "order_key")
@MappedCollection(idColumn = "id", keyColumn = "order_key")
List<DummyEntity2> list = new ArrayList<>();

String test;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -88,13 +91,37 @@ public BasicRelationalPersistentProperty(Property property, PersistentEntity<?,
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()
);
}

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

@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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*
* @author Kazuki Shimizu
* @author Florian Lüdiger
* @author Bastian Wilhelm
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
Expand All @@ -39,6 +40,9 @@

/**
* 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 "";
}
Original file line number Diff line number Diff line change
@@ -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 "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private static class DummyEntity {
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;
Expand Down
12 changes: 6 additions & 6 deletions src/main/asciidoc/jdbc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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>`.

Expand Down Expand Up @@ -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]
Expand All @@ -245,7 +245,7 @@ public class MyEntity {
@Id
Integer id;

@Column("CUSTOM_COLUMN_NAME")
@MappedCollection(idColumn = "CUSTOM_COLUMN_NAME")
Set<MySubEntity> name;
}

Expand All @@ -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]
Expand All @@ -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;
}

Expand Down