1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.type;
17
18 import java.sql.CallableStatement;
19 import java.sql.PreparedStatement;
20 import java.sql.ResultSet;
21 import java.sql.ResultSetMetaData;
22 import java.sql.SQLException;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import org.apache.ibatis.io.Resources;
27
28
29
30
31 public class UnknownTypeHandler extends BaseTypeHandler<Object> {
32
33 private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();
34
35 private TypeHandlerRegistry typeHandlerRegistry;
36
37 public UnknownTypeHandler(TypeHandlerRegistry typeHandlerRegistry) {
38 this.typeHandlerRegistry = typeHandlerRegistry;
39 }
40
41 @Override
42 public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
43 throws SQLException {
44 TypeHandler handler = resolveTypeHandler(parameter, jdbcType);
45 handler.setParameter(ps, i, parameter, jdbcType);
46 }
47
48 @Override
49 public Object getNullableResult(ResultSet rs, String columnName)
50 throws SQLException {
51 TypeHandler<?> handler = resolveTypeHandler(rs, columnName);
52 return handler.getResult(rs, columnName);
53 }
54
55 @Override
56 public Object getNullableResult(ResultSet rs, int columnIndex)
57 throws SQLException {
58 TypeHandler<?> handler = resolveTypeHandler(rs.getMetaData(), columnIndex);
59 if (handler == null || handler instanceof UnknownTypeHandler) {
60 handler = OBJECT_TYPE_HANDLER;
61 }
62 return handler.getResult(rs, columnIndex);
63 }
64
65 @Override
66 public Object getNullableResult(CallableStatement cs, int columnIndex)
67 throws SQLException {
68 return cs.getObject(columnIndex);
69 }
70
71 private TypeHandler<? extends Object> resolveTypeHandler(Object parameter, JdbcType jdbcType) {
72 TypeHandler<? extends Object> handler;
73 if (parameter == null) {
74 handler = OBJECT_TYPE_HANDLER;
75 } else {
76 handler = typeHandlerRegistry.getTypeHandler(parameter.getClass(), jdbcType);
77
78 if (handler == null || handler instanceof UnknownTypeHandler) {
79 handler = OBJECT_TYPE_HANDLER;
80 }
81 }
82 return handler;
83 }
84
85 private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {
86 try {
87 Map<String,Integer> columnIndexLookup;
88 columnIndexLookup = new HashMap<String,Integer>();
89 ResultSetMetaData rsmd = rs.getMetaData();
90 int count = rsmd.getColumnCount();
91 for (int i=1; i <= count; i++) {
92 String name = rsmd.getColumnName(i);
93 columnIndexLookup.put(name,i);
94 }
95 Integer columnIndex = columnIndexLookup.get(column);
96 TypeHandler<?> handler = null;
97 if (columnIndex != null) {
98 handler = resolveTypeHandler(rsmd, columnIndex);
99 }
100 if (handler == null || handler instanceof UnknownTypeHandler) {
101 handler = OBJECT_TYPE_HANDLER;
102 }
103 return handler;
104 } catch (SQLException e) {
105 throw new TypeException("Error determining JDBC type for column " + column + ". Cause: " + e, e);
106 }
107 }
108
109 private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer columnIndex) throws SQLException {
110 TypeHandler<?> handler = null;
111 JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);
112 Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);
113 if (javaType != null && jdbcType != null) {
114 handler = typeHandlerRegistry.getTypeHandler(javaType, jdbcType);
115 } else if (javaType != null) {
116 handler = typeHandlerRegistry.getTypeHandler(javaType);
117 } else if (jdbcType != null) {
118 handler = typeHandlerRegistry.getTypeHandler(jdbcType);
119 }
120 return handler;
121 }
122
123 private JdbcType safeGetJdbcTypeForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
124 try {
125 return JdbcType.forCode(rsmd.getColumnType(columnIndex));
126 } catch (Exception e) {
127 return null;
128 }
129 }
130
131 private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
132 try {
133 return Resources.classForName(rsmd.getColumnClassName(columnIndex));
134 } catch (Exception e) {
135 return null;
136 }
137 }
138 }