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

mybatis / mybatis-3 / 2686

01 Feb 2025 09:55PM UTC coverage: 87.093% (-0.1%) from 87.217%
2686

Pull #3379

github

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

3825 of 4663 branches covered (82.03%)

515 of 579 new or added lines in 36 files covered. (88.95%)

28 existing lines in 6 files now uncovered.

9912 of 11381 relevant lines covered (87.09%)

0.87 hits per line

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

68.42
/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
  private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();
1✔
37
  // TODO Rename to 'configuration' after removing the 'configuration' property(deprecated property) on parent class
38
  private final Configuration config;
39
  private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;
40

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

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

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

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

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

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

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

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

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

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

156
  private Class<?> safeGetClassForColumn(ResultSetMetaData rsmd, Integer columnIndex) {
157
    try {
158
      return Resources.classForName(rsmd.getColumnClassName(columnIndex));
1✔
159
    } catch (Exception e) {
×
160
      return null;
×
161
    }
162
  }
163
}
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

© 2025 Coveralls, Inc