• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / mybatis-3 / 2695

12 Feb 2025 06:57PM UTC coverage: 87.212% (-0.005%) from 87.217%
2695

Pull #3379

github

web-flow
Merge 1261a3400 into 12d286ea2
Pull Request #3379: Resolve type handler based on `java.lang.reflect.Type` instead of `Class` and respect runtime JDBC type

3820 of 4639 branches covered (82.35%)

525 of 591 new or added lines in 42 files covered. (88.83%)

13 existing lines in 4 files now uncovered.

9882 of 11331 relevant lines covered (87.21%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.86
/src/main/java/org/apache/ibatis/type/UnknownTypeHandler.java
1
/*
2
 *    Copyright 2009-2025 the original author or authors.
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *       https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
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
import java.util.function.Supplier;
26

27
import org.apache.ibatis.io.Resources;
28
import org.apache.ibatis.session.Configuration;
29

30
/**
31
 * @author Clinton Begin
32
 */
33
@Deprecated
34
public class UnknownTypeHandler extends BaseTypeHandler<Object> {
35

36
  // TODO Rename to 'configuration' after removing the 'configuration' property(deprecated property) on parent class
37
  private final Configuration config;
38
  private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;
39

40
  /**
41
   * The constructor that pass a MyBatis configuration.
42
   *
43
   * @param configuration
44
   *          a MyBatis configuration
45
   *
46
   * @since 3.5.4
47
   */
48
  public UnknownTypeHandler(Configuration configuration) {
1✔
49
    this.config = configuration;
1✔
50
    this.typeHandlerRegistrySupplier = configuration::getTypeHandlerRegistry;
1✔
51
  }
1✔
52

53
  /**
54
   * The constructor that pass the type handler registry.
55
   *
56
   * @param typeHandlerRegistry
57
   *          a type handler registry
58
   *
59
   * @deprecated Since 3.5.4, please use the {@link #UnknownTypeHandler(Configuration)}.
60
   */
61
  @Deprecated
62
  public UnknownTypeHandler(TypeHandlerRegistry typeHandlerRegistry) {
×
63
    this.config = new Configuration();
×
64
    this.typeHandlerRegistrySupplier = () -> typeHandlerRegistry;
×
65
  }
×
66

67
  @Override
68
  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
69
      throws SQLException {
70
    TypeHandler handler = resolveTypeHandler(parameter, jdbcType);
1✔
71
    handler.setParameter(ps, i, parameter, jdbcType);
1✔
72
  }
1✔
73

74
  @Override
75
  public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
76
    TypeHandler<?> handler = resolveTypeHandler(rs, columnName);
1✔
77
    return handler.getResult(rs, columnName);
1✔
78
  }
79

80
  @Override
81
  public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
82
    TypeHandler<?> handler = resolveTypeHandler(rs.getMetaData(), columnIndex);
1✔
83
    if (handler == null || handler instanceof UnknownTypeHandler) {
1!
NEW
84
      handler = ObjectTypeHandler.INSTANCE;
×
85
    }
86
    return handler.getResult(rs, columnIndex);
1✔
87
  }
88

89
  @Override
90
  public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
91
    return cs.getObject(columnIndex);
1✔
92
  }
93

94
  private TypeHandler<?> resolveTypeHandler(Object parameter, JdbcType jdbcType) {
95
    TypeHandler<?> handler;
96
    if (parameter == null) {
1!
NEW
97
      handler = ObjectTypeHandler.INSTANCE;
×
98
    } else {
99
      handler = typeHandlerRegistrySupplier.get().getTypeHandler(parameter.getClass(), jdbcType);
1✔
100
      // check if handler is null (issue #270)
101
      if (handler == null || handler instanceof UnknownTypeHandler) {
1!
NEW
102
        handler = ObjectTypeHandler.INSTANCE;
×
103
      }
104
    }
105
    return handler;
1✔
106
  }
107

108
  private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {
109
    try {
110
      Map<String, Integer> columnIndexLookup;
111
      columnIndexLookup = new HashMap<>();
1✔
112
      ResultSetMetaData rsmd = rs.getMetaData();
1✔
113
      int count = rsmd.getColumnCount();
1✔
114
      boolean useColumnLabel = config.isUseColumnLabel();
1✔
115
      for (int i = 1; i <= count; i++) {
1✔
116
        String name = useColumnLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i);
1!
117
        columnIndexLookup.put(name, i);
1✔
118
      }
119
      Integer columnIndex = columnIndexLookup.get(column);
1✔
120
      TypeHandler<?> handler = null;
1✔
121
      if (columnIndex != null) {
1!
122
        handler = resolveTypeHandler(rsmd, columnIndex);
1✔
123
      }
124
      if (handler == null || handler instanceof UnknownTypeHandler) {
1!
NEW
125
        handler = ObjectTypeHandler.INSTANCE;
×
126
      }
127
      return handler;
1✔
128
    } catch (SQLException e) {
×
129
      throw new TypeException("Error determining JDBC type for column " + column + ".  Cause: " + e, e);
×
130
    }
131
  }
132

133
  private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer columnIndex) {
134
    TypeHandler<?> handler = null;
1✔
135
    JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);
1✔
136
    Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);
1✔
137
    if (javaType != null && jdbcType != null) {
1!
138
      handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType, jdbcType);
1✔
139
    } else if (javaType != null) {
×
140
      handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType);
×
141
    } else if (jdbcType != null) {
×
142
      handler = typeHandlerRegistrySupplier.get().getTypeHandler(jdbcType);
×
143
    }
144
    return handler;
1✔
145
  }
146

147
  private JdbcType safeGetJdbcTypeForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
148
    try {
149
      return JdbcType.forCode(rsmd.getColumnType(columnIndex));
1✔
150
    } catch (Exception e) {
×
151
      return null;
×
152
    }
153
  }
154

155
  private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
156
    try {
157
      return Resources.classForName(rsmd.getColumnClassName(columnIndex));
1✔
158
    } catch (Exception e) {
×
159
      return null;
×
160
    }
161
  }
162
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc