Properly convert primitive array arguments.
Closes #945 Original pull request: #949.
This commit is contained in:
committed by
Mark Paluch
parent
80da756a42
commit
a55bdb46cc
@@ -41,4 +41,97 @@ class ArrayUtil {
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static Byte[] toObjectArray(byte[] primitiveArray) {
|
||||
|
||||
Byte[] objects = new Byte[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Short[] toObjectArray(short[] primitiveArray) {
|
||||
|
||||
Short[] objects = new Short[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Character[] toObjectArray(char[] primitiveArray) {
|
||||
|
||||
Character[] objects = new Character[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Integer[] toObjectArray(int[] primitiveArray) {
|
||||
|
||||
Integer[] objects = new Integer[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Long[] toObjectArray(long[] primitiveArray) {
|
||||
|
||||
Long[] objects = new Long[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Float[] toObjectArray(float[] primitiveArray) {
|
||||
|
||||
Float[] objects = new Float[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Double[] toObjectArray(double[] primitiveArray) {
|
||||
|
||||
Double[] objects = new Double[primitiveArray.length];
|
||||
for (int i = 0; i < primitiveArray.length; i++) {
|
||||
objects[i] = primitiveArray[i];
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
static Object[] convertToObjectArray(Object unknownArray) {
|
||||
|
||||
Class<?> componentType = unknownArray.getClass().getComponentType();
|
||||
|
||||
if (componentType.isPrimitive()) {
|
||||
if (componentType == byte.class) {
|
||||
return toObjectArray((byte[]) unknownArray);
|
||||
}
|
||||
if (componentType == short.class) {
|
||||
return toObjectArray((short[]) unknownArray);
|
||||
}
|
||||
if (componentType == char.class) {
|
||||
return toObjectArray((char[]) unknownArray);
|
||||
}
|
||||
if (componentType == int.class) {
|
||||
return toObjectArray((int[]) unknownArray);
|
||||
}
|
||||
if (componentType == long.class) {
|
||||
return toObjectArray((long[]) unknownArray);
|
||||
}
|
||||
if (componentType == float.class) {
|
||||
return toObjectArray((float[]) unknownArray);
|
||||
}
|
||||
if (componentType == double.class) {
|
||||
return toObjectArray((double[]) unknownArray);
|
||||
}
|
||||
}
|
||||
return (Object[]) unknownArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +297,9 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
|
||||
|
||||
Class<?> componentType = convertedValue.getClass().getComponentType();
|
||||
if (componentType != byte.class && componentType != Byte.class) {
|
||||
return JdbcValue.of(typeFactory.createArray((Object[]) convertedValue), JDBCType.ARRAY);
|
||||
|
||||
Object[] objectArray = ArrayUtil.convertToObjectArray(convertedValue);
|
||||
return JdbcValue.of(typeFactory.createArray(objectArray), JDBCType.ARRAY);
|
||||
}
|
||||
|
||||
if (componentType == Byte.class) {
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
@@ -35,8 +37,10 @@ import org.junit.Test;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.mapping.AggregateReference;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.support.JdbcUtil;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
|
||||
import org.springframework.data.relational.core.sql.IdentifierProcessing;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
/**
|
||||
@@ -47,9 +51,15 @@ import org.springframework.data.util.ClassTypeInformation;
|
||||
public class BasicJdbcConverterUnitTests {
|
||||
|
||||
JdbcMappingContext context = new JdbcMappingContext();
|
||||
BasicJdbcConverter converter = new BasicJdbcConverter(context, (identifier, path) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
});
|
||||
StubbedJdbcTypeFactory typeFactory = new StubbedJdbcTypeFactory();
|
||||
BasicJdbcConverter converter = new BasicJdbcConverter( //
|
||||
context, //
|
||||
(identifier, path) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
}, //
|
||||
new JdbcCustomConversions(), //
|
||||
typeFactory, IdentifierProcessing.ANSI //
|
||||
);
|
||||
|
||||
@Test // DATAJDBC-104, DATAJDBC-1384
|
||||
public void testTargetTypesForPropertyType() {
|
||||
@@ -110,14 +120,25 @@ public class BasicJdbcConverterUnitTests {
|
||||
LocalDateTime testLocalDateTime = LocalDateTime.of(2001, 2, 3, 4, 5, 6, 123456789);
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "localDateTime", testLocalDateTime);
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "localDate", LocalDate.of(2001, 2, 3));
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "localTime", LocalTime.of(1, 2, 3,123456789));
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "instant", testLocalDateTime.toInstant(ZoneOffset.UTC));
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "localTime", LocalTime.of(1, 2, 3, 123456789));
|
||||
checkConversionToTimestampAndBack(softly, persistentEntity, "instant",
|
||||
testLocalDateTime.toInstant(ZoneOffset.UTC));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void checkConversionToTimestampAndBack(SoftAssertions softly, RelationalPersistentEntity<?> persistentEntity, String propertyName,
|
||||
Object value) {
|
||||
@Test // #945
|
||||
public void conversionOfPrimitiveArrays() {
|
||||
|
||||
int[] ints = { 1, 2, 3, 4, 5 };
|
||||
JdbcValue converted = converter.writeJdbcValue(ints, ints.getClass(), JdbcUtil.sqlTypeFor(ints.getClass()));
|
||||
|
||||
assertThat(converted.getValue()).isInstanceOf(Array.class);
|
||||
assertThat(typeFactory.arraySource).containsExactly(1, 2, 3, 4, 5);
|
||||
}
|
||||
|
||||
private void checkConversionToTimestampAndBack(SoftAssertions softly, RelationalPersistentEntity<?> persistentEntity,
|
||||
String propertyName, Object value) {
|
||||
|
||||
RelationalPersistentProperty property = persistentEntity.getRequiredPersistentProperty(propertyName);
|
||||
|
||||
@@ -165,4 +186,14 @@ public class BasicJdbcConverterUnitTests {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class OtherEntity {}
|
||||
|
||||
private static class StubbedJdbcTypeFactory implements JdbcTypeFactory {
|
||||
public Object[] arraySource;
|
||||
|
||||
@Override
|
||||
public Array createArray(Object[] value) {
|
||||
arraySource = value;
|
||||
return mock(Array.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user