Skip to content

Commit 3812082

Browse files
committed
Introduce a type mapping
Detect the type of the Array from the component type of the Object[] that's passed in as parameter. Only regular Java types are mapped - for mapping interface types like java.sql.Clob etc. users would have to override the resolveTypeName() method.
1 parent 6d5db13 commit 3812082

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

src/main/java/org/apache/ibatis/type/ArrayTypeHandler.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,63 @@
1515
*/
1616
package org.apache.ibatis.type;
1717

18+
import java.math.BigDecimal;
19+
import java.math.BigInteger;
20+
import java.net.URL;
1821
import java.sql.Array;
1922
import java.sql.CallableStatement;
2023
import java.sql.PreparedStatement;
2124
import java.sql.ResultSet;
2225
import java.sql.SQLException;
26+
import java.sql.Time;
27+
import java.sql.Timestamp;
2328
import java.sql.Types;
29+
import java.time.LocalDate;
30+
import java.time.LocalDateTime;
31+
import java.time.LocalTime;
32+
import java.time.OffsetDateTime;
33+
import java.time.OffsetTime;
34+
import java.util.Calendar;
35+
import java.util.concurrent.ConcurrentHashMap;
2436

2537
/**
2638
* @author Clinton Begin
2739
*/
2840
public class ArrayTypeHandler extends BaseTypeHandler<Object> {
2941

42+
private static final ConcurrentHashMap<Class<?>, String> STANDARD_MAPPING;
43+
static {
44+
STANDARD_MAPPING = new ConcurrentHashMap<>();
45+
STANDARD_MAPPING.put(BigDecimal.class, "NUMERIC");
46+
STANDARD_MAPPING.put(BigInteger.class, "BIGINT");
47+
STANDARD_MAPPING.put(boolean.class, "BOOLEAN");
48+
STANDARD_MAPPING.put(Boolean.class, "BOOLEAN");
49+
STANDARD_MAPPING.put(byte[].class, "VARBINARY");
50+
STANDARD_MAPPING.put(byte.class, "TINYINT");
51+
STANDARD_MAPPING.put(Byte.class, "TINYINT");
52+
STANDARD_MAPPING.put(Calendar.class, "TIMESTAMP");
53+
STANDARD_MAPPING.put(java.sql.Date.class, "DATE");
54+
STANDARD_MAPPING.put(java.util.Date.class, "TIMESTAMP");
55+
STANDARD_MAPPING.put(double.class, "DOUBLE");
56+
STANDARD_MAPPING.put(Double.class, "DOUBLE");
57+
STANDARD_MAPPING.put(float.class, "REAL");
58+
STANDARD_MAPPING.put(Float.class, "REAL");
59+
STANDARD_MAPPING.put(int.class, "INTEGER");
60+
STANDARD_MAPPING.put(Integer.class, "INTEGER");
61+
STANDARD_MAPPING.put(LocalDate.class, "DATE");
62+
STANDARD_MAPPING.put(LocalDateTime.class, "TIMESTAMP");
63+
STANDARD_MAPPING.put(LocalTime.class, "TIME");
64+
STANDARD_MAPPING.put(long.class, "BIGINT");
65+
STANDARD_MAPPING.put(Long.class, "BIGINT");
66+
STANDARD_MAPPING.put(OffsetDateTime.class, "TIMESTAMP_WITH_TIMEZONE");
67+
STANDARD_MAPPING.put(OffsetTime.class, "TIME_WITH_TIMEZONE");
68+
STANDARD_MAPPING.put(Short.class, "SMALLINT");
69+
STANDARD_MAPPING.put(String.class, "VARCHAR");
70+
STANDARD_MAPPING.put(Time.class, "TIME");
71+
STANDARD_MAPPING.put(Timestamp.class, "TIMESTAMP");
72+
STANDARD_MAPPING.put(URL.class, "DATALINK");
73+
};
74+
3075
public ArrayTypeHandler() {
3176
super();
3277
}
@@ -38,23 +83,26 @@ protected void setNullParameter(PreparedStatement ps, int i, JdbcType jdbcType)
3883

3984
@Override
4085
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
41-
Array array = null;
4286
if (parameter instanceof Array) {
4387
// it's the user's responsibility to properly free() the Array instance
4488
ps.setArray(i, (Array)parameter);
45-
4689
}
4790
else {
4891
if (!parameter.getClass().isArray()) {
4992
throw new TypeException("ArrayType Handler requires SQL array or java array parameter and does not support type " + parameter.getClass());
5093
}
51-
Object[] values = (Object[])parameter;
52-
array = ps.getConnection().createArrayOf(jdbcType.name(), values);
94+
Class<?> componentType = parameter.getClass().getComponentType();
95+
String arrayTypeName = resolveTypeName(componentType);
96+
Array array = ps.getConnection().createArrayOf(arrayTypeName, (Object[])parameter);
5397
ps.setArray(i, array);
5498
array.free();
5599
}
56100
}
57101

102+
protected String resolveTypeName(Class<?> type) {
103+
return STANDARD_MAPPING.getOrDefault(type, "JAVA_OBJECT");
104+
}
105+
58106
@Override
59107
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
60108
return extractArray(rs.getArray(columnName));

src/test/java/org/apache/ibatis/type/ArrayTypeHandlerTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@
1818
import org.junit.jupiter.api.Test;
1919
import org.mockito.Mock;
2020

21+
2122
import java.sql.Array;
23+
import java.sql.Connection;
2224
import java.sql.Types;
2325

26+
import static org.mockito.ArgumentMatchers.any;
27+
import static org.mockito.ArgumentMatchers.anyString;
2428
import static org.junit.jupiter.api.Assertions.assertEquals;
2529
import static org.junit.jupiter.api.Assertions.assertNull;
2630
import static org.junit.jupiter.api.Assertions.assertThrows;
31+
import static org.mockito.Mockito.mock;
2732
import static org.mockito.Mockito.verify;
2833
import static org.mockito.Mockito.when;
2934

@@ -40,6 +45,19 @@ public void shouldSetParameter() throws Exception {
4045
TYPE_HANDLER.setParameter(ps, 1, mockArray, null);
4146
verify(ps).setArray(1, mockArray);
4247
}
48+
49+
@Test
50+
public void shouldSetStringArrayParameter() throws Exception {
51+
Connection connection = mock(Connection.class);
52+
when(ps.getConnection()).thenReturn(connection);
53+
54+
Array array = mock(Array.class);
55+
when(connection.createArrayOf(anyString(), any(String[].class))).thenReturn(array);
56+
57+
TYPE_HANDLER.setParameter(ps, 1, new String[] { "Hello World" }, JdbcType.ARRAY);
58+
verify(ps).setArray(1, array);
59+
verify(array).free();
60+
}
4361

4462
@Test
4563
public void shouldSetNullParameter() throws Exception {

0 commit comments

Comments
 (0)