DATAJDBC-259 - Reading and writing to SQL array types.
Currently works for HsqlDb and Postgres, since the others do not support an array column type. Original pull request: #113.
This commit is contained in:
committed by
Mark Paluch
parent
75ea44536f
commit
83ca6b4739
@@ -18,6 +18,8 @@ package org.springframework.data.jdbc.core;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.JDBCType;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -301,13 +303,30 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
||||
} else {
|
||||
|
||||
Object value = propertyAccessor.getProperty(property);
|
||||
Object convertedValue = converter.writeValue(value, ClassTypeInformation.from(property.getColumnType()));
|
||||
Object convertedValue = convertForWrite(property, value);
|
||||
|
||||
parameters.addValue(prefix + property.getColumnName(), convertedValue, JdbcUtil.sqlTypeFor(property.getColumnType()));
|
||||
}
|
||||
});
|
||||
|
||||
return parameters;
|
||||
}
|
||||
@Nullable
|
||||
private Object convertForWrite(RelationalPersistentProperty property, @Nullable Object value) {
|
||||
|
||||
Object convertedValue = converter.writeValue(value, ClassTypeInformation.from(property.getColumnType()));
|
||||
|
||||
if (convertedValue == null || !convertedValue.getClass().isArray()) {
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
Class<?> componentType = convertedValue.getClass().getComponentType();
|
||||
String typeName = JDBCType.valueOf(JdbcUtil.sqlTypeFor(componentType)).getName();
|
||||
|
||||
return operations.getJdbcOperations().execute(
|
||||
(Connection c) -> c.createArrayOf(typeName, (Object[]) convertedValue)
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
|
||||
@@ -110,7 +110,7 @@ public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
private Object readOrLoadProperty(ResultSet resultSet, @Nullable Object id, RelationalPersistentProperty property,
|
||||
String prefix) {
|
||||
|
||||
if (property.isCollectionLike() && id != null) {
|
||||
if (property.isCollectionOfEntitiesLike() && id != null) {
|
||||
return accessStrategy.findAllByProperty(id, property);
|
||||
} else if (property.isMap() && id != null) {
|
||||
return ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(accessStrategy.findAllByProperty(id, property));
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.data.convert.CustomConversions;
|
||||
import org.springframework.data.jdbc.core.mapping.AggregateReference;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
@@ -26,6 +29,9 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* {@link RelationalConverter} that uses a {@link MappingContext} to apply basic conversion of relational values to
|
||||
* property values.
|
||||
@@ -40,6 +46,8 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
public class BasicJdbcConverter extends BasicRelationalConverter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BasicJdbcConverter.class);
|
||||
|
||||
/**
|
||||
* Creates a new {@link BasicRelationalConverter} given {@link MappingContext}.
|
||||
*
|
||||
@@ -85,6 +93,14 @@ public class BasicJdbcConverter extends BasicRelationalConverter {
|
||||
return AggregateReference.to(readValue(value, idType));
|
||||
}
|
||||
|
||||
if (value instanceof Array) {
|
||||
try {
|
||||
return readValue(((Array) value).getArray(), type);
|
||||
} catch (SQLException | ConverterNotFoundException e ) {
|
||||
LOG.info("Failed to extract a value of type %s from an Array. Attempting to use standard conversions.", e);
|
||||
}
|
||||
}
|
||||
|
||||
return super.readValue(value, type);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ public class JdbcMappingContext extends RelationalMappingContext {
|
||||
|
||||
@Override
|
||||
protected boolean shouldCreatePersistentEntityFor(TypeInformation<?> type) {
|
||||
return super.shouldCreatePersistentEntityFor(type) && !AggregateReference.class.isAssignableFrom(type.getType());
|
||||
|
||||
return super.shouldCreatePersistentEntityFor(type) //
|
||||
&& !AggregateReference.class.isAssignableFrom(type.getType()) //
|
||||
&& !type.isCollectionLike();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,13 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.Assume;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -38,8 +42,10 @@ import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
import org.springframework.data.relational.core.conversion.RelationalConverter;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.Table;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
import org.springframework.test.annotation.ProfileValueSourceConfiguration;
|
||||
import org.springframework.test.annotation.ProfileValueUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.rules.SpringClassRule;
|
||||
import org.springframework.test.context.junit4.rules.SpringMethodRule;
|
||||
@@ -318,6 +324,102 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
assertThat(reloaded.content).extracting(e -> e.content).containsExactly("content");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void saveAndLoadAnEntityWithArray() {
|
||||
|
||||
// MySQL and other do not support array datatypes. See
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/data-type-overview.html
|
||||
assumeNot("mysql");
|
||||
assumeNot("mariadb");
|
||||
assumeNot("mssql");
|
||||
|
||||
ArrayOwner arrayOwner = new ArrayOwner();
|
||||
arrayOwner.digits = new String[] { "one", "two", "three" };
|
||||
|
||||
ArrayOwner saved = template.save(arrayOwner);
|
||||
|
||||
assertThat(saved.id).isNotNull();
|
||||
|
||||
ArrayOwner reloaded = template.findById(saved.id, ArrayOwner.class);
|
||||
|
||||
assertThat(reloaded).isNotNull();
|
||||
assertThat(reloaded.id).isEqualTo(saved.id);
|
||||
assertThat(reloaded.digits).isEqualTo(new String[] { "one", "two", "three" });
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void saveAndLoadAnEntityWithList() {
|
||||
|
||||
// MySQL and others do not support array datatypes. See
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/data-type-overview.html
|
||||
assumeNot("mysql");
|
||||
assumeNot("mariadb");
|
||||
assumeNot("mssql");
|
||||
|
||||
ListOwner arrayOwner = new ListOwner();
|
||||
arrayOwner.digits.addAll(Arrays.asList("one", "two", "three"));
|
||||
|
||||
ListOwner saved = template.save(arrayOwner);
|
||||
|
||||
assertThat(saved.id).isNotNull();
|
||||
|
||||
ListOwner reloaded = template.findById(saved.id, ListOwner.class);
|
||||
|
||||
assertThat(reloaded).isNotNull();
|
||||
assertThat(reloaded.id).isEqualTo(saved.id);
|
||||
assertThat(reloaded.digits).isEqualTo(Arrays.asList("one", "two", "three"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void saveAndLoadAnEntityWithSet() {
|
||||
|
||||
// MySQL and others do not support array datatypes. See
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/data-type-overview.html
|
||||
assumeNot("mysql");
|
||||
assumeNot("mariadb");
|
||||
assumeNot("mssql");
|
||||
|
||||
SetOwner setOwner = new SetOwner();
|
||||
setOwner.digits.addAll(Arrays.asList("one", "two", "three"));
|
||||
|
||||
SetOwner saved = template.save(setOwner);
|
||||
|
||||
assertThat(saved.id).isNotNull();
|
||||
|
||||
SetOwner reloaded = template.findById(saved.id, SetOwner.class);
|
||||
|
||||
assertThat(reloaded).isNotNull();
|
||||
assertThat(reloaded.id).isEqualTo(saved.id);
|
||||
assertThat(reloaded.digits).isEqualTo(new HashSet<>(Arrays.asList("one", "two", "three")));
|
||||
}
|
||||
|
||||
private static void assumeNot(String dbProfileName) {
|
||||
|
||||
Assume.assumeTrue("true"
|
||||
.equalsIgnoreCase(ProfileValueUtils.retrieveProfileValueSource(JdbcAggregateTemplateIntegrationTests.class)
|
||||
.get("current.database.is.not." + dbProfileName)));
|
||||
}
|
||||
|
||||
private static class ArrayOwner {
|
||||
@Id Long id;
|
||||
|
||||
String[] digits;
|
||||
}
|
||||
|
||||
@Table("ARRAY_OWNER")
|
||||
private static class ListOwner {
|
||||
@Id Long id;
|
||||
|
||||
List<String> digits = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Table("ARRAY_OWNER")
|
||||
private static class SetOwner {
|
||||
@Id Long id;
|
||||
|
||||
Set<String> digits = new HashSet<>();
|
||||
}
|
||||
|
||||
private static LegoSet createLegoSet() {
|
||||
|
||||
LegoSet entity = new LegoSet();
|
||||
@@ -333,8 +435,7 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
@Data
|
||||
static class LegoSet {
|
||||
|
||||
@Column("id1")
|
||||
@Id private Long id;
|
||||
@Column("id1") @Id private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -345,16 +446,14 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
@Data
|
||||
static class Manual {
|
||||
|
||||
@Column("id2")
|
||||
@Id private Long id;
|
||||
@Column("id2") @Id private Long id;
|
||||
private String content;
|
||||
|
||||
}
|
||||
|
||||
static class OneToOneParent {
|
||||
|
||||
@Column("id3")
|
||||
@Id private Long id;
|
||||
@Column("id3") @Id private Long id;
|
||||
private String content;
|
||||
|
||||
private ChildNoId child;
|
||||
@@ -366,8 +465,7 @@ public class JdbcAggregateTemplateIntegrationTests {
|
||||
|
||||
static class ListParent {
|
||||
|
||||
@Column("id4")
|
||||
@Id private Long id;
|
||||
@Column("id4") @Id private Long id;
|
||||
String name;
|
||||
List<ElementNoId> content = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -9,3 +9,5 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR
|
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
|
||||
CREATE TABLE ARRAY_OWNER (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL);
|
||||
@@ -8,4 +8,4 @@ CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT AUTO_INCREMENT PRIMARY KEY, content
|
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR(30));
|
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
@@ -1,15 +1,15 @@
|
||||
DROP TABLE IF EXISTS LEGO_SET;
|
||||
DROP TABLE IF EXISTS MANUAL;
|
||||
DROP TABLE IF EXISTS LEGO_SET;
|
||||
CREATE TABLE LEGO_SET ( id1 BIGINT IDENTITY PRIMARY KEY, NAME VARCHAR(30));
|
||||
CREATE TABLE MANUAL ( id2 BIGINT IDENTITY PRIMARY KEY, LEGO_SET BIGINT, ALTERNATIVE BIGINT, CONTENT VARCHAR(2000));
|
||||
ALTER TABLE MANUAL ADD FOREIGN KEY (LEGO_SET) REFERENCES LEGO_SET(id1);
|
||||
|
||||
DROP TABLE IF EXISTS ONE_TO_ONE_PARENT;
|
||||
DROP TABLE IF EXISTS Child_No_Id;
|
||||
DROP TABLE IF EXISTS ONE_TO_ONE_PARENT;
|
||||
CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT IDENTITY PRIMARY KEY, content VARCHAR(30));
|
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT BIGINT PRIMARY KEY, content VARCHAR(30));
|
||||
|
||||
DROP TABLE IF EXISTS LIST_PARENT;
|
||||
DROP TABLE IF EXISTS element_no_id;
|
||||
DROP TABLE IF EXISTS LIST_PARENT;
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT IDENTITY PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT);
|
||||
@@ -12,3 +12,5 @@ CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR
|
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 SERIAL PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT INTEGER);
|
||||
|
||||
CREATE TABLE ARRAY_OWNER (ID SERIAL PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL);
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.relational.core.mapping;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Date;
|
||||
@@ -139,7 +140,17 @@ public class BasicRelationalPersistentProperty extends AnnotationBasedPersistent
|
||||
|
||||
Class columnType = columnTypeIfEntity(getActualType());
|
||||
|
||||
return columnType == null ? columnTypeForNonEntity(getActualType()) : columnType;
|
||||
if (columnType != null) {
|
||||
return columnType;
|
||||
}
|
||||
|
||||
Class componentColumnType = columnTypeForNonEntity(getActualType());
|
||||
|
||||
if (isCollectionOfSimpleTypeLike()) {
|
||||
return Array.newInstance(componentColumnType, 0).getClass();
|
||||
}
|
||||
|
||||
return componentColumnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,7 +45,7 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio
|
||||
|
||||
/**
|
||||
* The SQL type constant used when using this property as a parameter for a SQL statement.
|
||||
*
|
||||
*
|
||||
* @return Must not be {@code null}.
|
||||
* @see java.sql.Types
|
||||
*/
|
||||
@@ -84,4 +84,12 @@ public interface RelationalPersistentProperty extends PersistentProperty<Relatio
|
||||
default String getEmbeddedPrefix() {
|
||||
return null;
|
||||
};
|
||||
|
||||
default boolean isCollectionOfEntitiesLike() {
|
||||
return isCollectionLike() && isEntity();
|
||||
}
|
||||
|
||||
default boolean isCollectionOfSimpleTypeLike() {
|
||||
return isCollectionLike() && !isEntity();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,12 +70,10 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
|
||||
RelationalPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DummyEntity.class);
|
||||
|
||||
checkTargetType(softly, persistentEntity, "someEnum", String.class);
|
||||
checkTargetType(softly, persistentEntity, "localDateTime", Date.class);
|
||||
checkTargetType(softly, persistentEntity, "zonedDateTime", String.class);
|
||||
checkTargetType(softly, persistentEntity, "uuid", UUID.class);
|
||||
checkTargetType(softly, entity, "someEnum", String.class);
|
||||
checkTargetType(softly, entity, "localDateTime", Date.class);
|
||||
checkTargetType(softly, entity, "zonedDateTime", String.class);
|
||||
checkTargetType(softly, entity, "uuid", UUID.class);
|
||||
|
||||
softly.assertAll();
|
||||
}
|
||||
@@ -83,8 +81,6 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
@Test // DATAJDBC-106
|
||||
public void detectsAnnotatedColumnName() {
|
||||
|
||||
RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class);
|
||||
|
||||
assertThat(entity.getRequiredPersistentProperty("name").getColumnName()).isEqualTo("dummy_name");
|
||||
assertThat(entity.getRequiredPersistentProperty("localDateTime").getColumnName())
|
||||
.isEqualTo("dummy_last_updated_at");
|
||||
@@ -93,9 +89,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
@Test // DATAJDBC-218
|
||||
public void detectsAnnotatedColumnAndKeyName() {
|
||||
|
||||
RelationalPersistentProperty listProperty = context //
|
||||
.getRequiredPersistentEntity(DummyEntity.class) //
|
||||
.getRequiredPersistentProperty("someList");
|
||||
RelationalPersistentProperty listProperty = entity.getRequiredPersistentProperty("someList");
|
||||
|
||||
assertThat(listProperty.getReverseColumnName()).isEqualTo("dummy_column_name");
|
||||
assertThat(listProperty.getKeyColumn()).isEqualTo("dummy_key_column_name");
|
||||
@@ -130,6 +124,40 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-259
|
||||
public void classificationOfCollectionLikeProperties() {
|
||||
|
||||
RelationalPersistentProperty listOfString = entity.getRequiredPersistentProperty("listOfString");
|
||||
RelationalPersistentProperty arrayOfString = entity.getRequiredPersistentProperty("arrayOfString");
|
||||
RelationalPersistentProperty listOfEntity = entity.getRequiredPersistentProperty("listOfEntity");
|
||||
RelationalPersistentProperty arrayOfEntity = entity.getRequiredPersistentProperty("arrayOfEntity");
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
|
||||
softly.assertThat(listOfString.isCollectionOfSimpleTypeLike())
|
||||
.describedAs("listOfString is a Collection of a simple type.").isEqualTo(true);
|
||||
softly.assertThat(arrayOfString.isCollectionOfSimpleTypeLike())
|
||||
.describedAs("arrayOfString is a Collection of a simple type.").isTrue();
|
||||
softly.assertThat(listOfEntity.isCollectionOfSimpleTypeLike())
|
||||
.describedAs("listOfEntity is a Collection of a simple type.").isFalse();
|
||||
softly.assertThat(arrayOfEntity.isCollectionOfSimpleTypeLike())
|
||||
.describedAs("arrayOfEntity is a Collection of a simple type.").isFalse();
|
||||
|
||||
BiConsumer<RelationalPersistentProperty, String> checkEitherOr = (p, s) -> softly
|
||||
.assertThat(p.isCollectionOfSimpleTypeLike()).describedAs(s + " contains either simple types or entities")
|
||||
.isNotEqualTo(p.isCollectionOfEntitiesLike());
|
||||
|
||||
checkEitherOr.accept(listOfString,"listOfString");
|
||||
checkEitherOr.accept(arrayOfString,"arrayOfString");
|
||||
checkEitherOr.accept(listOfEntity,"listOfEntity");
|
||||
checkEitherOr.accept(arrayOfEntity,"arrayOfEntity");
|
||||
|
||||
softly.assertThat(arrayOfString.getColumnType()).isEqualTo(String[].class);
|
||||
softly.assertThat(listOfString.getColumnType()).isEqualTo(String[].class);
|
||||
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
private void checkTargetType(SoftAssertions softly, RelationalPersistentEntity<?> persistentEntity,
|
||||
String propertyName, Class<?> expected) {
|
||||
|
||||
@@ -146,9 +174,14 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
private final SomeEnum someEnum;
|
||||
private final LocalDateTime localDateTime;
|
||||
private final ZonedDateTime zonedDateTime;
|
||||
private final List<String> listField;
|
||||
private final UUID uuid;
|
||||
|
||||
// DATAJDBC-259
|
||||
private final List<String> listOfString;
|
||||
private final String[] arrayOfString;
|
||||
private final List<OtherEntity> listOfEntity;
|
||||
private final OtherEntity[] arrayOfEntity;
|
||||
|
||||
@Column(value = "dummy_column_name", keyColumn = "dummy_key_column_name") private List<Integer> someList;
|
||||
|
||||
// DATACMNS-106
|
||||
@@ -184,4 +217,7 @@ public class BasicRelationalPersistentPropertyUnitTests {
|
||||
private static class EmbeddableEntity {
|
||||
private final String embeddedTest;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class OtherEntity {}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,8 @@ The properties of the following types are currently supported:
|
||||
|
||||
* `java.util.Date`, `java.time.LocalDate`, `java.time.LocalDateTime`, and `java.time.LocalTime`
|
||||
|
||||
* Arrays and Collections of the types mentioned above can be mapped to columns of array type if your database supports that.
|
||||
|
||||
* Anything your database driver accepts.
|
||||
|
||||
* References to other entities. They are considered a one-to-one relationship, or an embedded type.
|
||||
|
||||
Reference in New Issue
Block a user