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.
This commit is contained in:
committed by
Jens Schauder
parent
f69aa31958
commit
5830b83cf4
@@ -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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
@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 {
|
||||
static class WithId {
|
||||
@Id Long withIdId;
|
||||
Second second;
|
||||
@Embedded("sec") Second second2;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "sec") Second second2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
@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 {
|
||||
.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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
@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 {
|
||||
NoIdChain3 chain3;
|
||||
}
|
||||
|
||||
static class WithImmutableValue {
|
||||
static class WithNullableEmbeddedImmutableValue {
|
||||
|
||||
@Id Long id;
|
||||
@Embedded ImmutableValue embeddedImmutableValue;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL) ImmutableValue embeddedImmutableValue;
|
||||
}
|
||||
|
||||
static class WithPrimitiveImmutableValue {
|
||||
static class WithEmptyEmbeddedImmutableValue {
|
||||
|
||||
@Id Long id;
|
||||
@Embedded ImmutablePrimitiveValue embeddedImmutablePrimitiveValue;
|
||||
@Embedded(onEmpty = OnEmpty.USE_EMPTY) ImmutableValue embeddedImmutableValue;
|
||||
}
|
||||
|
||||
static class WithEmbeddedPrimitiveImmutableValue {
|
||||
|
||||
@Id Long id;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL) ImmutablePrimitiveValue embeddedImmutablePrimitiveValue;
|
||||
}
|
||||
|
||||
@Value
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@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 {
|
||||
|
||||
@Id Long id;
|
||||
|
||||
@Embedded("prefix_") EmbeddedWithReference embedded;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") EmbeddedWithReference embedded;
|
||||
}
|
||||
|
||||
static class EmbeddedWithReference {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@Id Long id;
|
||||
|
||||
@Embedded("prefix_") Embeddable prefixedEmbeddable;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Embeddable prefixedEmbeddable;
|
||||
}
|
||||
|
||||
@Value
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
String test;
|
||||
|
||||
@Embedded("prefix_")
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
|
||||
Embeddable embeddable;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
String test;
|
||||
|
||||
@Embedded("prefix_")
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
|
||||
Embeddable embeddable;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
String test;
|
||||
|
||||
@Embedded("prefix_")
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_")
|
||||
Embeddable embeddable;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) //
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
* @return prefix for columns in the embedded value object. Default is an empty String
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* 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. An empty {@link String} by default.
|
||||
*/
|
||||
String prefix() default "";
|
||||
|
||||
/**
|
||||
* Load strategy to be used {@link Embedded#onEmpty()}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @since 1.1
|
||||
*/
|
||||
enum OnEmpty {
|
||||
USE_NULL, USE_EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
static class EmbeddedReferenceEntity {
|
||||
|
||||
@Id final Long id;
|
||||
@Embedded("prefix_") Element other;
|
||||
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Element other;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
|
||||
@@ -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 {
|
||||
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() {
|
||||
|
||||
@@ -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 {
|
||||
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]]
|
||||
|
||||
Reference in New Issue
Block a user