Browse Source

DATAJDBC-374 - Add onEmpty attribute to Embedded annotation.

The onEmpty attribute allows to define if an embedded entity should be set to null or a default instance if all properties backing the entity are actually null.

    @Embedded(onEmpty = USE_NULL)
    EmbeddedEntity embeddedEntity;

Original pull request: #154.
pull/156/head
Christoph Strobl 7 years ago committed by Jens Schauder
parent
commit
5830b83cf4
  1. 7
      spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java
  2. 7
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/PersistentPropertyPathExtensionUnitTests.java
  3. 46
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java
  4. 11
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java
  5. 3
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedImmutableIntegrationTests.java
  6. 7
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedIntegrationTests.java
  7. 3
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedNotInAggregateRootIntegrationTests.java
  8. 3
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedWithCollectionIntegrationTests.java
  9. 3
      spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/JdbcRepositoryEmbeddedWithReferenceIntegrationTests.java
  10. 2
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentProperty.java
  11. 27
      spring-data-relational/src/main/java/org/springframework/data/relational/core/mapping/Embedded.java
  12. 3
      spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java
  13. 5
      spring-data-relational/src/test/java/org/springframework/data/relational/core/mapping/BasicRelationalPersistentPropertyUnitTests.java
  14. 10
      src/main/asciidoc/jdbc.adoc

7
spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java

@ -37,6 +37,8 @@ import org.springframework.data.mapping.context.MappingContext; @@ -37,6 +37,8 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.relational.core.conversion.BasicRelationalConverter;
import org.springframework.data.relational.core.conversion.RelationalConverter;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@ -375,6 +377,11 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc @@ -375,6 +377,11 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
private Object readEmbeddedEntityFrom(@Nullable Object idValue, RelationalPersistentProperty property) {
ReadingContext<?> newContext = extendBy(property);
if(OnEmpty.USE_EMPTY.equals(property.findAnnotation(Embedded.class).onEmpty())) {
return newContext.createInstanceInternal(idValue);
}
return newContext.hasInstanceValues(idValue) ? newContext.createInstanceInternal(idValue) : null;
}

7
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/PersistentPropertyPathExtensionUnitTests.java

@ -23,6 +23,7 @@ import org.springframework.data.annotation.Id; @@ -23,6 +23,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@ -217,7 +218,7 @@ public class PersistentPropertyPathExtensionUnitTests { @@ -217,7 +218,7 @@ public class PersistentPropertyPathExtensionUnitTests {
static class DummyEntity {
@Id Long entityId;
Second second;
@Embedded("sec") Second second2;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "sec") Second second2;
List<Second> secondList;
WithId withId;
}
@ -225,7 +226,7 @@ public class PersistentPropertyPathExtensionUnitTests { @@ -225,7 +226,7 @@ public class PersistentPropertyPathExtensionUnitTests {
@SuppressWarnings("unused")
static class Second {
Third third;
@Embedded("thrd") Third third2;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "thrd") Third third2;
}
@SuppressWarnings("unused")
@ -237,7 +238,7 @@ public class PersistentPropertyPathExtensionUnitTests { @@ -237,7 +238,7 @@ public class PersistentPropertyPathExtensionUnitTests {
static class WithId {
@Id Long withIdId;
Second second;
@Embedded("sec") Second second2;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "sec") Second second2;
}
}

46
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java

@ -54,6 +54,7 @@ import org.springframework.data.annotation.PersistenceConstructor; @@ -54,6 +54,7 @@ import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.NamingStrategy;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
@ -295,13 +296,13 @@ public class EntityRowMapperUnitTests { @@ -295,13 +296,13 @@ public class EntityRowMapperUnitTests {
}
@Test // DATAJDBC-370
public void simpleImmutableEmbeddedGetsProperlyExtracted() throws SQLException {
public void simpleNullableImmutableEmbeddedGetsProperlyExtracted() throws SQLException {
ResultSet rs = mockResultSet(asList("id", "value"), //
ID_FOR_ENTITY_NOT_REFERENCING_MAP, "ru'Ha'");
rs.next();
WithImmutableValue extracted = createRowMapper(WithImmutableValue.class).mapRow(rs, 1);
WithNullableEmbeddedImmutableValue extracted = createRowMapper(WithNullableEmbeddedImmutableValue.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
@ -309,6 +310,21 @@ public class EntityRowMapperUnitTests { @@ -309,6 +310,21 @@ public class EntityRowMapperUnitTests {
.containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, new ImmutableValue("ru'Ha'"));
}
@Test // DATAJDBC-374
public void simpleEmptyImmutableEmbeddedGetsProperlyExtracted() throws SQLException {
ResultSet rs = mockResultSet(asList("id", "value"), //
ID_FOR_ENTITY_NOT_REFERENCING_MAP, null);
rs.next();
WithEmptyEmbeddedImmutableValue extracted = createRowMapper(WithEmptyEmbeddedImmutableValue.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
.extracting(e -> e.id, e -> e.embeddedImmutableValue) //
.containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, new ImmutableValue(null));
}
@Test // DATAJDBC-370
@SneakyThrows
public void simplePrimitiveImmutableEmbeddedGetsProperlyExtracted() {
@ -317,7 +333,7 @@ public class EntityRowMapperUnitTests { @@ -317,7 +333,7 @@ public class EntityRowMapperUnitTests {
ID_FOR_ENTITY_NOT_REFERENCING_MAP, 24);
rs.next();
WithPrimitiveImmutableValue extracted = createRowMapper(WithPrimitiveImmutableValue.class).mapRow(rs, 1);
WithEmbeddedPrimitiveImmutableValue extracted = createRowMapper(WithEmbeddedPrimitiveImmutableValue.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
@ -332,7 +348,7 @@ public class EntityRowMapperUnitTests { @@ -332,7 +348,7 @@ public class EntityRowMapperUnitTests {
ID_FOR_ENTITY_NOT_REFERENCING_MAP, null);
rs.next();
WithImmutableValue extracted = createRowMapper(WithImmutableValue.class).mapRow(rs, 1);
WithNullableEmbeddedImmutableValue extracted = createRowMapper(WithNullableEmbeddedImmutableValue.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
@ -380,7 +396,7 @@ public class EntityRowMapperUnitTests { @@ -380,7 +396,7 @@ public class EntityRowMapperUnitTests {
ID_FOR_ENTITY_NOT_REFERENCING_MAP, null);
rs.next();
WithPrimitiveImmutableValue extracted = createRowMapper(WithPrimitiveImmutableValue.class).mapRow(rs, 1);
WithEmbeddedPrimitiveImmutableValue extracted = createRowMapper(WithEmbeddedPrimitiveImmutableValue.class).mapRow(rs, 1);
assertThat(extracted) //
.isNotNull() //
@ -465,7 +481,7 @@ public class EntityRowMapperUnitTests { @@ -465,7 +481,7 @@ public class EntityRowMapperUnitTests {
@Id Long id;
String name;
@Embedded("prefix_") Trivial children;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Trivial children;
}
private static class DontUseSetter {
@ -533,16 +549,22 @@ public class EntityRowMapperUnitTests { @@ -533,16 +549,22 @@ public class EntityRowMapperUnitTests {
NoIdChain3 chain3;
}
static class WithImmutableValue {
static class WithNullableEmbeddedImmutableValue {
@Id Long id;
@Embedded(onEmpty = OnEmpty.USE_NULL) ImmutableValue embeddedImmutableValue;
}
static class WithEmptyEmbeddedImmutableValue {
@Id Long id;
@Embedded ImmutableValue embeddedImmutableValue;
@Embedded(onEmpty = OnEmpty.USE_EMPTY) ImmutableValue embeddedImmutableValue;
}
static class WithPrimitiveImmutableValue {
static class WithEmbeddedPrimitiveImmutableValue {
@Id Long id;
@Embedded ImmutablePrimitiveValue embeddedImmutablePrimitiveValue;
@Embedded(onEmpty = OnEmpty.USE_NULL) ImmutablePrimitiveValue embeddedImmutablePrimitiveValue;
}
@Value
@ -559,13 +581,13 @@ public class EntityRowMapperUnitTests { @@ -559,13 +581,13 @@ public class EntityRowMapperUnitTests {
@Id Long id;
String level0;
@Embedded("level1_") EmbeddedWithEmbedded level1;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "level1_") EmbeddedWithEmbedded level1;
}
static class EmbeddedWithEmbedded {
Object value;
@Embedded("level2_") ImmutableValue level2;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "level2_") ImmutableValue level2;
}
// Infrastructure for assertions and constructing mocks

11
spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/SqlGeneratorEmbeddedUnitTests.java

@ -27,6 +27,7 @@ import org.springframework.data.jdbc.core.PropertyPathTestingUtils; @@ -27,6 +27,7 @@ import org.springframework.data.jdbc.core.PropertyPathTestingUtils;
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
@ -245,16 +246,16 @@ public class SqlGeneratorEmbeddedUnitTests { @@ -245,16 +246,16 @@ public class SqlGeneratorEmbeddedUnitTests {
@Column("id1") @Id Long id;
@Embedded("prefix_") CascadedEmbedded prefixedEmbeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") CascadedEmbedded prefixedEmbeddable;
@Embedded CascadedEmbedded embeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL) CascadedEmbedded embeddable;
}
@SuppressWarnings("unused")
static class CascadedEmbedded {
String test;
@Embedded("prefix2_") Embeddable prefixedEmbeddable;
@Embedded Embeddable embeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix2_") Embeddable prefixedEmbeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL) Embeddable embeddable;
}
@SuppressWarnings("unused")
@ -268,7 +269,7 @@ public class SqlGeneratorEmbeddedUnitTests { @@ -268,7 +269,7 @@ public class SqlGeneratorEmbeddedUnitTests {
@Id Long id;
@Embedded("prefix_") EmbeddedWithReference embedded;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") EmbeddedWithReference embedded;
}
static class EmbeddedWithReference {

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

@ -33,6 +33,7 @@ import org.springframework.data.annotation.Id; @@ -33,6 +33,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
import org.springframework.data.jdbc.testing.TestConfiguration;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -99,7 +100,7 @@ public class JdbcRepositoryEmbeddedImmutableIntegrationTests { @@ -99,7 +100,7 @@ public class JdbcRepositoryEmbeddedImmutableIntegrationTests {
@Id Long id;
@Embedded("prefix_") Embeddable prefixedEmbeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Embeddable prefixedEmbeddable;
}
@Value

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

@ -31,6 +31,7 @@ import org.springframework.data.annotation.Id; @@ -31,6 +31,7 @@ import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
import org.springframework.data.jdbc.testing.TestConfiguration;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -250,16 +251,16 @@ public class JdbcRepositoryEmbeddedIntegrationTests { @@ -250,16 +251,16 @@ public class JdbcRepositoryEmbeddedIntegrationTests {
@Id Long id;
@Embedded("prefix_") CascadedEmbeddable prefixedEmbeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") CascadedEmbeddable prefixedEmbeddable;
@Embedded CascadedEmbeddable embeddable;
@Embedded(onEmpty = OnEmpty.USE_NULL) CascadedEmbeddable embeddable;
}
@Data
static class CascadedEmbeddable {
String test;
@Embedded("prefix2_")
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix2_")
Embeddable embeddable;
}

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

@ -32,6 +32,7 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; @@ -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.Embedded.OnEmpty;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -246,7 +247,7 @@ public class JdbcRepositoryEmbeddedNotInAggregateRootIntegrationTests { @@ -246,7 +247,7 @@ public class JdbcRepositoryEmbeddedNotInAggregateRootIntegrationTests {
String test;
@Embedded("prefix_")
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
Embeddable embeddable;
}

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

@ -32,6 +32,7 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; @@ -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.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
@ -249,7 +250,7 @@ public class JdbcRepositoryEmbeddedWithCollectionIntegrationTests { @@ -249,7 +250,7 @@ public class JdbcRepositoryEmbeddedWithCollectionIntegrationTests {
String test;
@Embedded("prefix_")
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
Embeddable embeddable;
}

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

@ -32,6 +32,7 @@ import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory; @@ -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.Embedded.OnEmpty;
import org.springframework.data.repository.CrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -236,7 +237,7 @@ public class JdbcRepositoryEmbeddedWithReferenceIntegrationTests { @@ -236,7 +237,7 @@ public class JdbcRepositoryEmbeddedWithReferenceIntegrationTests {
String test;
@Embedded("prefix_")
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
Embeddable embeddable;
}

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

@ -84,7 +84,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent @@ -84,7 +84,7 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
this.isEmbedded = Lazy.of(() -> Optional.ofNullable(findAnnotation(Embedded.class)).isPresent());
this.embeddedPrefix = Lazy.of(() -> Optional.ofNullable(findAnnotation(Embedded.class)) //
.map(Embedded::value) //
.map(Embedded::prefix) //
.orElse(""));
this.columnName = Lazy.of(() -> Optional.ofNullable(findAnnotation(Column.class)) //

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

@ -23,15 +23,38 @@ import java.lang.annotation.Target; @@ -23,15 +23,38 @@ import java.lang.annotation.Target;
/**
* The annotation to configure a value object as embedded in the current table.
* <p />
* Depending on the {@link OnEmpty value} of {@link #onEmpty()} the property is set to {@literal null} or an empty
* instance in the case all embedded values are {@literal null} when reading from the result set.
*
* @author Bastian Wilhelm
* @author Christoph Strobl
* @since 1.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Documented
public @interface Embedded {
/**
* Set the load strategy for the embedded object if all contained fields yield {@literal null} values.
*
* @return never {@link} null.
*/
OnEmpty onEmpty();
/**
* @return prefix for columns in the embedded value object. Default is an empty String
* @return prefix for columns in the embedded value object. An empty {@link String} by default.
*/
String value() default "";
String prefix() default "";
/**
* Load strategy to be used {@link Embedded#onEmpty()}.
*
* @author Christoph Strobl
* @since 1.1
*/
enum OnEmpty {
USE_NULL, USE_EMPTY
}
}

3
spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java

@ -39,6 +39,7 @@ import org.springframework.data.relational.core.conversion.DbAction.Insert; @@ -39,6 +39,7 @@ import org.springframework.data.relational.core.conversion.DbAction.Insert;
import org.springframework.data.relational.core.conversion.DbAction.InsertRoot;
import org.springframework.data.relational.core.conversion.DbAction.UpdateRoot;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.lang.Nullable;
@ -588,7 +589,7 @@ public class RelationalEntityWriterUnitTests { @@ -588,7 +589,7 @@ public class RelationalEntityWriterUnitTests {
static class EmbeddedReferenceEntity {
@Id final Long id;
@Embedded("prefix_") Element other;
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Element other;
}
@RequiredArgsConstructor

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

@ -30,6 +30,7 @@ import org.assertj.core.api.SoftAssertions; @@ -30,6 +30,7 @@ import org.assertj.core.api.SoftAssertions;
import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.relational.core.mapping.Embedded.OnEmpty;
/**
* Unit tests for the {@link BasicRelationalPersistentProperty}.
@ -188,10 +189,10 @@ public class BasicRelationalPersistentPropertyUnitTests { @@ -188,10 +189,10 @@ public class BasicRelationalPersistentPropertyUnitTests {
private @Column("dummy_name") String name;
// DATAJDBC-111
private @Embedded EmbeddableEntity embeddableEntity;
private @Embedded(onEmpty = OnEmpty.USE_NULL) EmbeddableEntity embeddableEntity;
// DATAJDBC-111
private @Embedded("prefix") EmbeddableEntity prefixedEmbeddableEntity;
private @Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix") EmbeddableEntity prefixedEmbeddableEntity;
@Column("dummy_last_updated_at")
public LocalDateTime getLocalDateTime() {

10
src/main/asciidoc/jdbc.adoc

@ -288,14 +288,19 @@ Embedded entities are used to have value objects in your java data model, even i @@ -288,14 +288,19 @@ Embedded entities are used to have value objects in your java data model, even i
In the following example you see, that `MyEntity` is mapped with the `@Embedded` annotation.
The consequence of this is, that in the database a table `my_entity` with the two columns `id` and `name` (from the `EmbeddedEntity` class) is expected.
However, if the `name` column is actually `null` within the result set, the entire property `embeddedEntity` will be set to null according to the `onEmpty` of `@Embedded`, which ``null``s objects when all nested properties are `null`. +
Opposite to this behavior `USE_EMPTY` tries to create a new instance using either a default constructor or one that accepts nullable parameter values from the result set.
.Sample Code of embedding objects
====
[source, java]
----
public class MyEntity {
@Id
Integer id;
@Embedded
@Embedded(onEmpty = USE_NULL) <1>
EmbeddedEntity embeddedEntity;
}
@ -303,9 +308,10 @@ public class EmbeddedEntity { @@ -303,9 +308,10 @@ public class EmbeddedEntity {
String name;
}
----
<1> ``Null``s `embeddedEntity` if `name` in `null`. Use `USE_EMPTY` to instanciate `embeddedEntity` with a potential `null` value for the `name` property.
====
If you need a value object multiple times in an entity, this can be achieved with the optional `value` element of the `@Embedded` annotation.
If you need a value object multiple times in an entity, this can be achieved with the optional `prefix` element of the `@Embedded` annotation.
This element represents a prefix and is prepend for each column name in the embedded object.
[[jdbc.entity-persistence.state-detection-strategies]]

Loading…
Cancel
Save