From ae779c65bcb10aec6606d43c1c2bacf596f938c8 Mon Sep 17 00:00:00 2001 From: "Andrew J. Lazarus" Date: Wed, 8 Dec 2021 16:50:59 -0800 Subject: [PATCH] Add support for LocalDate[] mappings #406 --- .../type/array/LocalDateArrayType.java | 50 ++++++++++ .../type/array/internal/ArrayUtil.java | 9 +- .../internal/ListArrayTypeDescriptor.java | 3 + .../LocalDateArrayTypeDescriptor.java | 17 ++++ .../hibernate/type/array/ArrayTypeTest.java | 14 +++ .../type/array/ListArrayTypeTest.java | 34 +++++++ .../hibernate/type/model/BaseEntity.java | 1 + .../type/array/LocalDateArrayType.java | 54 +++++++++++ .../type/array/internal/ArrayUtil.java | 56 +++++++++-- .../internal/ListArrayTypeDescriptor.java | 3 + .../LocalDateArrayTypeDescriptor.java | 17 ++++ .../hibernate/type/array/ArrayTypeTest.java | 14 +++ .../type/array/ListArrayTypeTest.java | 94 +++++++++++++------ .../hibernate/type/model/BaseEntity.java | 1 + 14 files changed, 330 insertions(+), 37 deletions(-) create mode 100644 hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java create mode 100644 hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java create mode 100644 hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java create mode 100644 hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java diff --git a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java new file mode 100644 index 000000000..3ebbe089a --- /dev/null +++ b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java @@ -0,0 +1,50 @@ +package com.vladmihalcea.hibernate.type.array; + +import com.vladmihalcea.hibernate.type.array.internal.AbstractArrayType; +import com.vladmihalcea.hibernate.type.array.internal.LocalDateArrayTypeDescriptor; +import com.vladmihalcea.hibernate.type.util.Configuration; +import com.vladmihalcea.hibernate.type.util.ParameterizedParameterType; +import org.hibernate.usertype.DynamicParameterizedType; + +import java.util.Properties; + +/** + * Maps a {@code java.Time.LocalDate[]} array on a PostgreSQL date[] ARRAY type. Multidimensional arrays are + * supported as well, as + * explained in this article. + *

+ * For more details about how to use it, check out + * this + * article on vladmihalcea.com. + * + * @author Andrew Lazarus, based on DateArrayType by Guillaume Briand + */ + +public class LocalDateArrayType extends AbstractArrayType { + + public static final LocalDateArrayType INSTANCE = + new LocalDateArrayType(); + + public LocalDateArrayType() { + super( + new LocalDateArrayTypeDescriptor() + ); + } + + public LocalDateArrayType(Configuration configuration) { + super( + new LocalDateArrayTypeDescriptor(), configuration + ); + } + + public LocalDateArrayType(Class arrayClass) { + this(); + Properties parameters = new Properties(); + parameters.put(DynamicParameterizedType.PARAMETER_TYPE, new ParameterizedParameterType(arrayClass)); + setParameterValues(parameters); + } + + public String getName() { + return "localdate-array"; + } +} diff --git a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java index 7d277133e..1274de565 100644 --- a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java +++ b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java @@ -125,7 +125,7 @@ public static Object[] wrapArray(Object originalArray) { } /** - * Unwarp {@link Object[]} array to an array of the provided type + * Unwrap {@link Object[]} array to an array of the provided type * * @param originalArray original array * @param arrayClass array class @@ -193,6 +193,13 @@ public static T unwrapArray(Object[] originalArray, Class arrayClass) { Array.set(array, i, objectValue); } return array; + } else if (java.time.LocalDate[].class.equals(arrayClass) && java.sql.Date[].class.equals(originalArray.getClass())) { + // special case because conversion is neither with ctor nor valueOf + Object[] array = (Object[]) Array.newInstance(java.time.LocalDate.class, originalArray.length); + for (int i = 0; i < array.length; ++i) { + array[i] = originalArray[i] != null ? ((java.sql.Date) originalArray[i]).toLocalDate() : null; + } + return (T) array; } else if(arrayClass.getComponentType() != null && arrayClass.getComponentType().isArray()) { int arrayLength = originalArray.length; Object[] array = (Object[]) Array.newInstance(arrayClass.getComponentType(), arrayLength); diff --git a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java index 1cdc1fc1b..681fdd27c 100644 --- a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java +++ b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java @@ -10,6 +10,7 @@ import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.math.BigDecimal; +import java.time.LocalDate; import java.util.*; /** @@ -130,6 +131,8 @@ public void setParameterValues(Properties parameters) { sqlArrayType = "boolean"; } else if (BigDecimal.class.isAssignableFrom(arrayElementClass)) { sqlArrayType = "decimal"; + } else if (LocalDate.class.isAssignableFrom(arrayElementClass)) { + sqlArrayType = "date"; } else { throw new UnsupportedOperationException("The " + arrayElementClass + " is not supported yet!"); } diff --git a/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java new file mode 100644 index 000000000..44d897522 --- /dev/null +++ b/hibernate-types-52/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java @@ -0,0 +1,17 @@ +package com.vladmihalcea.hibernate.type.array.internal; + +/** + * @author Vlad Mihalcea + */ +public class LocalDateArrayTypeDescriptor + extends AbstractArrayTypeDescriptor { + + public LocalDateArrayTypeDescriptor() { + super(java.time.LocalDate[].class); + } + + @Override + protected String getSqlArrayType() { + return "date"; + } +} diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java index 38f057c7c..211134aa9 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java @@ -95,6 +95,7 @@ public void test() { event.setDateValues(new Date[]{date1, date2}); event.setTimestampValues(new Date[]{date1, date2}); event.setDecimalValues(new BigDecimal[]{BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.TEN}); + event.setLocalDateValues(new LocalDate[]{LocalDate.of(2022, 3, 22), LocalDate.of(2021, 4, 21)}); event.setSensorBooleanValues(new Boolean[]{false, true, true}); entityManager.persist(event); @@ -112,6 +113,7 @@ public void test() { assertArrayEquals(new Date[]{date1, date2}, event.getDateValues()); assertArrayEquals(new Date[]{date1, date2}, event.getTimestampValues()); assertArrayEquals(new BigDecimal[]{BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.TEN}, event.getDecimalValues()); + assertArrayEquals(new LocalDate[]{LocalDate.of(2022, 3, 22), LocalDate.of(2021, 4, 21)}, event.getLocalDateValues()); assertArrayEquals(new Boolean[]{false, true, true}, event.getSensorBooleanValues()); }); @@ -201,6 +203,10 @@ public static class Event extends BaseEntity { @Column(name = "decimal_values", columnDefinition = "decimal[]") private BigDecimal[] decimalValues; + @Type(type = "localdate-array") + @Column(name = "localdate_values", columnDefinition = "date[]") + private LocalDate[] localDateValues; + @Type(type = "sensor-state-array") @Column(name = "sensor_states", columnDefinition = "sensor_state[]") private SensorState[] sensorStates; @@ -280,6 +286,14 @@ public BigDecimal[] getDecimalValues() { public void setDecimalValues(BigDecimal[] decimalValues) { this.decimalValues = decimalValues; } + + public LocalDate[] getLocalDateValues() { + return localDateValues; + } + + public void setLocalDateValues(LocalDate[] localDateValues) { + this.localDateValues = localDateValues; + } } public enum SensorState { diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java index be76d7bc0..97a1b47b3 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java @@ -123,6 +123,12 @@ public void test() { BigDecimal.TEN ) ) + .setLocalDateValues( + Arrays.asList( + LocalDate.of(2022, 3, 22), + LocalDate.of(2021, 4, 21) + ) + ) ); }); @@ -195,6 +201,13 @@ public void test() { ), event.getDecimalValues() ); + assertEquals( + Arrays.asList( + LocalDate.of(2022, 3, 22), + LocalDate.of(2021, 4, 21) + ), + event.getLocalDateValues() + ); }); doInJPA(entityManager -> { @@ -245,6 +258,7 @@ public void testMixingNullValues() { event.setDateValues(Arrays.asList(null, date)); event.setTimestampValues(Arrays.asList(null, date)); event.setDecimalValues(Arrays.asList(null, BigDecimal.TEN)); + event.setLocalDateValues(Arrays.asList(null, LocalDate.of(2021, 4, 21))); entityManager.persist(event); }); @@ -261,6 +275,7 @@ public void testMixingNullValues() { assertArrayEquals(new Date[]{null, date}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{null, date}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{null, BigDecimal.TEN}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{null, LocalDate.of(2021, 4, 21)}, event.getLocalDateValues().toArray()); }); } @@ -284,6 +299,7 @@ public void testNullValues() { event.setDateValues(Arrays.asList(null, null)); event.setTimestampValues(Arrays.asList(null, null)); event.setDecimalValues(Arrays.asList(null, null)); + event.setLocalDateValues(Arrays.asList(null, null)); entityManager.persist(event); }); @@ -300,6 +316,7 @@ public void testNullValues() { assertArrayEquals(new Date[]{null, null}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{null, null}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{null, null}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{null, null}, event.getLocalDateValues().toArray()); }); } @@ -323,6 +340,7 @@ public void testEmptyArrays() { event.setDateValues(Collections.emptyList()); event.setTimestampValues(Collections.emptyList()); event.setDecimalValues(Collections.emptyList()); + event.setLocalDateValues(Collections.emptyList()); entityManager.persist(event); }); @@ -339,6 +357,7 @@ public void testEmptyArrays() { assertArrayEquals(new Date[]{}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{}, event.getLocalDateValues().toArray()); }); } @@ -429,6 +448,13 @@ public static class Event { ) private List decimalValues; + @Type(type = "list-array") + @Column( + name = "localdate_values", + columnDefinition = "date[]" + ) + private List localDateValues; + public Long getId() { return id; } @@ -528,6 +554,14 @@ public Event setDecimalValues(List decimalValues) { return this; } + public List getLocalDateValues() { + return localDateValues; + } + + public Event setLocalDateValues(List localDateValues) { + this.localDateValues = localDateValues; + return this; + } } @Test diff --git a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java index e0eb23686..032a8346d 100644 --- a/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java +++ b/hibernate-types-52/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java @@ -22,6 +22,7 @@ @TypeDef(name = "date-array", typeClass = DateArrayType.class), @TypeDef(name = "timestamp-array", typeClass = TimestampArrayType.class), @TypeDef(name = "decimal-array", typeClass = DecimalArrayType.class), + @TypeDef(name = "localdate-array", typeClass = LocalDateArrayType.class), @TypeDef(name = "json", typeClass = JsonStringType.class), @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class), @TypeDef(name = "jsonb-node", typeClass = JsonNodeBinaryType.class), diff --git a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java new file mode 100644 index 000000000..80e9eeb28 --- /dev/null +++ b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/LocalDateArrayType.java @@ -0,0 +1,54 @@ +package com.vladmihalcea.hibernate.type.array; + +import com.vladmihalcea.hibernate.type.array.internal.AbstractArrayType; +import com.vladmihalcea.hibernate.type.array.internal.LocalDateArrayTypeDescriptor; +import com.vladmihalcea.hibernate.type.util.Configuration; +import com.vladmihalcea.hibernate.type.util.ParameterizedParameterType; +import org.hibernate.usertype.DynamicParameterizedType; + +import java.util.Properties; + +/** + * Maps a {@code java.Time.LocalDate[]} array on a PostgreSQL date[] ARRAY type. Multidimensional arrays are + * supported as well, as + * explained in this article. + *

+ * For more details about how to use it, check out + * this + * article on vladmihalcea.com. + * + * @author Andrew Lazarus, based on DateArrayType by Guillaume Briand + */ + +public class LocalDateArrayType extends AbstractArrayType { + + public static final com.vladmihalcea.hibernate.type.array.LocalDateArrayType INSTANCE = + new com.vladmihalcea.hibernate.type.array.LocalDateArrayType(); + + public LocalDateArrayType() { + super( + new LocalDateArrayTypeDescriptor() + ); + } + + public LocalDateArrayType(Configuration configuration) { + super( + new LocalDateArrayTypeDescriptor(), configuration + ); + } + + public LocalDateArrayType(Class arrayClass) { + this(); + Properties parameters = new Properties(); + parameters.put(DynamicParameterizedType.PARAMETER_TYPE, new ParameterizedParameterType(arrayClass)); + setParameterValues(parameters); + } + + public LocalDateArrayType(org.hibernate.type.spi.TypeBootstrapContext typeBootstrapContext) { + this(new Configuration(typeBootstrapContext.getConfigurationSettings())); + } + + public String getName() { + return "localdate-array"; + } +} diff --git a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java index 7d277133e..b76d1a179 100644 --- a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java +++ b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ArrayUtil.java @@ -1,6 +1,6 @@ package com.vladmihalcea.hibernate.type.array.internal; -import java.lang.reflect.Array; +import java.lang.reflect.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -125,7 +125,7 @@ public static Object[] wrapArray(Object originalArray) { } /** - * Unwarp {@link Object[]} array to an array of the provided type + * Unwrap {@link Object[]} array to an array of the provided type * * @param originalArray original array * @param arrayClass array class @@ -193,6 +193,13 @@ public static T unwrapArray(Object[] originalArray, Class arrayClass) { Array.set(array, i, objectValue); } return array; + } else if (java.time.LocalDate[].class.equals(arrayClass) && java.sql.Date[].class.equals(originalArray.getClass())) { + // special case because conversion is neither with ctor nor valueOf + Object[] array = (Object[]) Array.newInstance(java.time.LocalDate.class, originalArray.length); + for (int i = 0; i < array.length; ++i) { + array[i] = originalArray[i] != null ? ((java.sql.Date) originalArray[i]).toLocalDate() : null; + } + return (T) array; } else if(arrayClass.getComponentType() != null && arrayClass.getComponentType().isArray()) { int arrayLength = originalArray.length; Object[] array = (Object[]) Array.newInstance(arrayClass.getComponentType(), arrayLength); @@ -203,10 +210,47 @@ public static T unwrapArray(Object[] originalArray, Class arrayClass) { } return (T) array; } else { - if(arrayClass.isInstance(originalArray)) { + if (arrayClass.isInstance(originalArray)) { return (T) originalArray; } else { - return (T) Arrays.copyOf(originalArray, originalArray.length, (Class) arrayClass); + final Class targetComponentType = arrayClass.getComponentType(); + + if(originalArray.length > 0 && targetComponentType.isAssignableFrom(originalArray[0].getClass())) { + Object[] array = (Object[]) Array.newInstance(targetComponentType, originalArray.length); + + for (int i = 0; i < array.length; ++i) { + array[i] = originalArray[i]; + } + return (T) array; + } + + final Class originalComponentType = originalArray.getClass().getComponentType(); + if (targetComponentType.isAssignableFrom(originalComponentType)) { + return (T) Arrays.copyOf(originalArray, originalArray.length, (Class) arrayClass); + } else { + try { + Constructor constructor = + targetComponentType.getConstructor(originalComponentType); + Object[] array = (Object[]) Array.newInstance(targetComponentType, originalArray.length); + for (int i = 0; i < array.length; ++i) { + array[i] = constructor.newInstance(originalArray[i]); + } + return (T) array; + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { + // just try again + } + try { + Method valueOf = targetComponentType.getMethod("valueOf", originalComponentType); + Object[] array = (Object[]) Array.newInstance(targetComponentType, originalArray.length); + for (int i = 0; i < array.length; ++i) { + array[i] = valueOf.invoke(null, originalArray[i]); // null because it is static method + } + return (T) array; + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + // at this point there is no recovery? + throw new org.hibernate.HibernateException(e) ; + } + } } } } @@ -214,9 +258,9 @@ public static T unwrapArray(Object[] originalArray, Class arrayClass) { /** * Create array from its {@link String} representation. * - * @param string string representation + * @param string string representation * @param arrayClass array class - * @param array element type + * @param array element type * @return array */ public static T fromString(String string, Class arrayClass) { diff --git a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java index 1cdc1fc1b..681fdd27c 100644 --- a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java +++ b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/ListArrayTypeDescriptor.java @@ -10,6 +10,7 @@ import java.lang.reflect.Type; import java.lang.reflect.WildcardType; import java.math.BigDecimal; +import java.time.LocalDate; import java.util.*; /** @@ -130,6 +131,8 @@ public void setParameterValues(Properties parameters) { sqlArrayType = "boolean"; } else if (BigDecimal.class.isAssignableFrom(arrayElementClass)) { sqlArrayType = "decimal"; + } else if (LocalDate.class.isAssignableFrom(arrayElementClass)) { + sqlArrayType = "date"; } else { throw new UnsupportedOperationException("The " + arrayElementClass + " is not supported yet!"); } diff --git a/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java new file mode 100644 index 000000000..44d897522 --- /dev/null +++ b/hibernate-types-55/src/main/java/com/vladmihalcea/hibernate/type/array/internal/LocalDateArrayTypeDescriptor.java @@ -0,0 +1,17 @@ +package com.vladmihalcea.hibernate.type.array.internal; + +/** + * @author Vlad Mihalcea + */ +public class LocalDateArrayTypeDescriptor + extends AbstractArrayTypeDescriptor { + + public LocalDateArrayTypeDescriptor() { + super(java.time.LocalDate[].class); + } + + @Override + protected String getSqlArrayType() { + return "date"; + } +} diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java index 38f057c7c..211134aa9 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ArrayTypeTest.java @@ -95,6 +95,7 @@ public void test() { event.setDateValues(new Date[]{date1, date2}); event.setTimestampValues(new Date[]{date1, date2}); event.setDecimalValues(new BigDecimal[]{BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.TEN}); + event.setLocalDateValues(new LocalDate[]{LocalDate.of(2022, 3, 22), LocalDate.of(2021, 4, 21)}); event.setSensorBooleanValues(new Boolean[]{false, true, true}); entityManager.persist(event); @@ -112,6 +113,7 @@ public void test() { assertArrayEquals(new Date[]{date1, date2}, event.getDateValues()); assertArrayEquals(new Date[]{date1, date2}, event.getTimestampValues()); assertArrayEquals(new BigDecimal[]{BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.TEN}, event.getDecimalValues()); + assertArrayEquals(new LocalDate[]{LocalDate.of(2022, 3, 22), LocalDate.of(2021, 4, 21)}, event.getLocalDateValues()); assertArrayEquals(new Boolean[]{false, true, true}, event.getSensorBooleanValues()); }); @@ -201,6 +203,10 @@ public static class Event extends BaseEntity { @Column(name = "decimal_values", columnDefinition = "decimal[]") private BigDecimal[] decimalValues; + @Type(type = "localdate-array") + @Column(name = "localdate_values", columnDefinition = "date[]") + private LocalDate[] localDateValues; + @Type(type = "sensor-state-array") @Column(name = "sensor_states", columnDefinition = "sensor_state[]") private SensorState[] sensorStates; @@ -280,6 +286,14 @@ public BigDecimal[] getDecimalValues() { public void setDecimalValues(BigDecimal[] decimalValues) { this.decimalValues = decimalValues; } + + public LocalDate[] getLocalDateValues() { + return localDateValues; + } + + public void setLocalDateValues(LocalDate[] localDateValues) { + this.localDateValues = localDateValues; + } } public enum SensorState { diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java index be76d7bc0..c93ae3106 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/array/ListArrayTypeTest.java @@ -106,14 +106,14 @@ public void test() { LocalDate.of(1991, 12, 31) .atStartOfDay() .atZone(ZoneId.systemDefault()) - .toInstant() + .toInstant() ), - Date.from( - LocalDate.of(1990, 1, 1) - .atStartOfDay() - .atZone(ZoneId.systemDefault()) - .toInstant() - ) + Date.from( + LocalDate.of(1990, 1, 1) + .atStartOfDay() + .atZone(ZoneId.systemDefault()) + .toInstant() + ) ) ) .setDecimalValues( @@ -123,6 +123,12 @@ public void test() { BigDecimal.TEN ) ) + .setLocalDateValues( + Arrays.asList( + LocalDate.of(2022, 3, 22), + LocalDate.of(2021, 4, 21) + ) + ) ); }); @@ -195,29 +201,36 @@ public void test() { ), event.getDecimalValues() ); + assertEquals( + Arrays.asList( + LocalDate.of(2022, 3, 22), + LocalDate.of(2021, 4, 21) + ), + event.getLocalDateValues() + ); }); doInJPA(entityManager -> { List events = entityManager.createNativeQuery( "select " + - " id, " + - " sensor_ids, " + - " sensor_names, " + - " sensor_values, " + - " sensor_states " + - "from event ", Tuple.class) - .unwrap(org.hibernate.query.NativeQuery.class) - .addScalar("sensor_ids", UUIDArrayType.INSTANCE) - .addScalar("sensor_names", StringArrayType.INSTANCE) - .addScalar("sensor_values", IntArrayType.INSTANCE) - .addScalar( - "sensor_states", - new EnumArrayType( - SensorState[].class, - "sensor_state" + " id, " + + " sensor_ids, " + + " sensor_names, " + + " sensor_values, " + + " sensor_states " + + "from event ", Tuple.class) + .unwrap(org.hibernate.query.NativeQuery.class) + .addScalar("sensor_ids", UUIDArrayType.INSTANCE) + .addScalar("sensor_names", StringArrayType.INSTANCE) + .addScalar("sensor_values", IntArrayType.INSTANCE) + .addScalar( + "sensor_states", + new EnumArrayType( + SensorState[].class, + "sensor_state" + ) ) - ) - .getResultList(); + .getResultList(); assertEquals(2, events.size()); }); @@ -245,6 +258,7 @@ public void testMixingNullValues() { event.setDateValues(Arrays.asList(null, date)); event.setTimestampValues(Arrays.asList(null, date)); event.setDecimalValues(Arrays.asList(null, BigDecimal.TEN)); + event.setLocalDateValues(Arrays.asList(null, LocalDate.of(2021, 4, 21))); entityManager.persist(event); }); @@ -261,12 +275,13 @@ public void testMixingNullValues() { assertArrayEquals(new Date[]{null, date}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{null, date}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{null, BigDecimal.TEN}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{null, LocalDate.of(2021, 4, 21)}, event.getLocalDateValues().toArray()); }); } - + @Test public void testNullValues() { - + doInJPA(entityManager -> { Event nullEvent = new Event(); nullEvent.setId(0L); @@ -284,6 +299,7 @@ public void testNullValues() { event.setDateValues(Arrays.asList(null, null)); event.setTimestampValues(Arrays.asList(null, null)); event.setDecimalValues(Arrays.asList(null, null)); + event.setLocalDateValues(Arrays.asList(null, null)); entityManager.persist(event); }); @@ -300,6 +316,7 @@ public void testNullValues() { assertArrayEquals(new Date[]{null, null}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{null, null}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{null, null}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{null, null}, event.getLocalDateValues().toArray()); }); } @@ -323,6 +340,7 @@ public void testEmptyArrays() { event.setDateValues(Collections.emptyList()); event.setTimestampValues(Collections.emptyList()); event.setDecimalValues(Collections.emptyList()); + event.setLocalDateValues(Collections.emptyList()); entityManager.persist(event); }); @@ -339,6 +357,7 @@ public void testEmptyArrays() { assertArrayEquals(new Date[]{}, event.getDateValues().toArray()); assertArrayEquals(new Date[]{}, event.getTimestampValues().toArray()); assertArrayEquals(new BigDecimal[]{}, event.getDecimalValues().toArray()); + assertArrayEquals(new LocalDate[]{}, event.getLocalDateValues().toArray()); }); } @@ -417,18 +436,25 @@ public static class Event { @Type(type = "list-array") @Column( - name = "timestamp_values", - columnDefinition = "timestamp[]" + name = "timestamp_values", + columnDefinition = "timestamp[]" ) private List timestampValues; @Type(type = "list-array") @Column( - name = "decimal_values", - columnDefinition = "decimal[]" + name = "decimal_values", + columnDefinition = "decimal[]" ) private List decimalValues; + @Type(type = "list-array") + @Column( + name = "localdate_values", + columnDefinition = "date[]" + ) + private List localDateValues; + public Long getId() { return id; } @@ -528,6 +554,14 @@ public Event setDecimalValues(List decimalValues) { return this; } + public List getLocalDateValues() { + return localDateValues; + } + + public Event setLocalDateValues(List localDateValues) { + this.localDateValues = localDateValues; + return this; + } } @Test diff --git a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java index e0eb23686..032a8346d 100644 --- a/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java +++ b/hibernate-types-55/src/test/java/com/vladmihalcea/hibernate/type/model/BaseEntity.java @@ -22,6 +22,7 @@ @TypeDef(name = "date-array", typeClass = DateArrayType.class), @TypeDef(name = "timestamp-array", typeClass = TimestampArrayType.class), @TypeDef(name = "decimal-array", typeClass = DecimalArrayType.class), + @TypeDef(name = "localdate-array", typeClass = LocalDateArrayType.class), @TypeDef(name = "json", typeClass = JsonStringType.class), @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class), @TypeDef(name = "jsonb-node", typeClass = JsonNodeBinaryType.class),