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

mybatis / ibatis-2 / 736

29 Dec 2025 12:23AM UTC coverage: 65.571% (-0.03%) from 65.597%
736

push

github

web-flow
Merge pull request #339 from hazendaz/master

Key set cleanup to use size directly increasing speed for same result

1598 of 2797 branches covered (57.13%)

4 of 4 new or added lines in 1 file covered. (100.0%)

149 existing lines in 7 files now uncovered.

5047 of 7697 relevant lines covered (65.57%)

0.66 hits per line

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

82.72
/src/main/java/com/ibatis/sqlmap/engine/mapping/result/ResultMap.java
1
/*
2
 * Copyright 2004-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 com.ibatis.sqlmap.engine.mapping.result;
17

18
import com.ibatis.common.beans.Probe;
19
import com.ibatis.common.beans.ProbeFactory;
20
import com.ibatis.common.jdbc.exception.NestedSQLException;
21
import com.ibatis.sqlmap.client.SqlMapException;
22
import com.ibatis.sqlmap.engine.exchange.DataExchange;
23
import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
24
import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
25
import com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader;
26
import com.ibatis.sqlmap.engine.mapping.sql.Sql;
27
import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
28
import com.ibatis.sqlmap.engine.scope.ErrorContext;
29
import com.ibatis.sqlmap.engine.scope.StatementScope;
30
import com.ibatis.sqlmap.engine.type.DomCollectionTypeMarker;
31
import com.ibatis.sqlmap.engine.type.DomTypeMarker;
32
import com.ibatis.sqlmap.engine.type.TypeHandler;
33
import com.ibatis.sqlmap.engine.type.TypeHandlerFactory;
34

35
import java.sql.ResultSet;
36
import java.sql.SQLException;
37
import java.util.ArrayList;
38
import java.util.Collection;
39
import java.util.HashMap;
40
import java.util.HashSet;
41
import java.util.Iterator;
42
import java.util.List;
43
import java.util.Map;
44
import java.util.Set;
45
import java.util.StringTokenizer;
46

47
import javax.xml.parsers.DocumentBuilderFactory;
48
import javax.xml.parsers.ParserConfigurationException;
49

50
import org.w3c.dom.Document;
51

52
/**
53
 * Basic implementation of ResultMap interface.
54
 */
55
public class ResultMap {
56

57
  /** The Constant PROBE. */
58
  private static final Probe PROBE = ProbeFactory.getProbe();
1✔
59

60
  /** The Constant KEY_SEPARATOR. */
61
  private static final String KEY_SEPARATOR = "\002";
62

63
  /** The id. */
64
  private String id;
65

66
  /** The result class. */
67
  private Class resultClass;
68

69
  /** The result mappings. */
70
  // DO NOT ACCESS EITHER OF THESE OUTSIDE OF THEIR BEAN GETTER/SETTER
71
  private ResultMapping[] resultMappings;
72

73
  /** The remappable result mappings. */
74
  private ThreadLocal remappableResultMappings = new ThreadLocal();
1✔
75

76
  /** The data exchange. */
77
  private DataExchange dataExchange;
78

79
  /** The nested result mappings. */
80
  private List nestedResultMappings;
81

82
  /** The discriminator. */
83
  private Discriminator discriminator;
84

85
  /** The group by props. */
86
  private Set groupByProps;
87

88
  /** The xml name. */
89
  private String xmlName;
90

91
  /** The resource. */
92
  private String resource;
93

94
  /** The delegate. */
95
  protected SqlMapExecutorDelegate delegate;
96

97
  /** The allow remapping. */
98
  protected boolean allowRemapping = false;
1✔
99

100
  /** The Constant NO_VALUE. */
101
  public static final Object NO_VALUE = new Object();
1✔
102

103
  /**
104
   * Constructor to pass a SqlMapExecutorDelegate in.
105
   *
106
   * @param delegate
107
   *          - the SqlMapExecutorDelegate
108
   */
109
  public ResultMap(SqlMapExecutorDelegate delegate) {
1✔
110
    this.delegate = delegate;
1✔
111
  }
1✔
112

113
  /**
114
   * Getter for the SqlMapExecutorDelegate.
115
   *
116
   * @return - the delegate
117
   */
118
  public SqlMapExecutorDelegate getDelegate() {
119
    return delegate;
1✔
120
  }
121

122
  /**
123
   * Gets the id.
124
   *
125
   * @return the id
126
   */
127
  public String getId() {
128
    return id;
1✔
129
  }
130

131
  /**
132
   * Setter for the ID.
133
   *
134
   * @param id
135
   *          - the new ID
136
   */
137
  public void setId(String id) {
138
    this.id = id;
1✔
139
  }
1✔
140

141
  /**
142
   * Gets the result class.
143
   *
144
   * @return the result class
145
   */
146
  public Class getResultClass() {
147
    return resultClass;
1✔
148
  }
149

150
  /**
151
   * Gets the unique key.
152
   *
153
   * @param keyPrefix
154
   *          the key prefix
155
   * @param values
156
   *          the values
157
   *
158
   * @return the unique key
159
   */
160
  public Object getUniqueKey(String keyPrefix, Object[] values) {
161
    if (groupByProps == null) {
1✔
162
      return null;
1✔
163
    }
164

165
    StringBuilder keyBuffer;
166
    if (keyPrefix != null) {
1✔
167
      keyBuffer = new StringBuilder(keyPrefix);
1✔
168
    } else {
169
      keyBuffer = new StringBuilder();
1✔
170
    }
171
    for (int i = 0; i < getResultMappings().length; i++) {
1✔
172
      String propertyName = getResultMappings()[i].getPropertyName();
1✔
173
      if (groupByProps.contains(propertyName)) {
1✔
174
        keyBuffer.append(values[i]);
1✔
175
        keyBuffer.append('-');
1✔
176
      }
177
    }
178
    if (keyBuffer.length() < 1) {
1!
UNCOV
179
      return null;
×
180
    }
181
    // seperator value not likely to appear in a database
182
    keyBuffer.append(KEY_SEPARATOR);
1✔
183
    return keyBuffer.toString();
1✔
184
  }
185

186
  /**
187
   * Gets the unique key.
188
   *
189
   * @param values
190
   *          the values
191
   *
192
   * @return the unique key
193
   */
194
  public Object getUniqueKey(Object[] values) {
UNCOV
195
    return getUniqueKey(null, values);
×
196
  }
197

198
  /**
199
   * Setter for the result class (what the results will be mapped into).
200
   *
201
   * @param resultClass
202
   *          - the result class
203
   */
204
  public void setResultClass(Class resultClass) {
205
    this.resultClass = resultClass;
1✔
206
  }
1✔
207

208
  /**
209
   * Getter for the DataExchange object to be used.
210
   *
211
   * @return - the DataExchange object
212
   */
213
  public DataExchange getDataExchange() {
UNCOV
214
    return dataExchange;
×
215
  }
216

217
  /**
218
   * Setter for the DataExchange object to be used.
219
   *
220
   * @param dataExchange
221
   *          - the new DataExchange object
222
   */
223
  public void setDataExchange(DataExchange dataExchange) {
UNCOV
224
    this.dataExchange = dataExchange;
×
UNCOV
225
  }
×
226

227
  /**
228
   * Getter (used by DomDataExchange) for the xml name of the results.
229
   *
230
   * @return - the name
231
   */
232
  public String getXmlName() {
233
    return xmlName;
1✔
234
  }
235

236
  /**
237
   * Setter (used by the SqlMapBuilder) for the xml name of the results.
238
   *
239
   * @param xmlName
240
   *          - the name
241
   */
242
  public void setXmlName(String xmlName) {
243
    this.xmlName = xmlName;
1✔
244
  }
1✔
245

246
  /**
247
   * Getter for the resource (used to report errors).
248
   *
249
   * @return - the resource
250
   */
251
  public String getResource() {
252
    return resource;
1✔
253
  }
254

255
  /**
256
   * Setter for the resource (used by the SqlMapBuilder).
257
   *
258
   * @param resource
259
   *          - the resource name
260
   */
261
  public void setResource(String resource) {
262
    this.resource = resource;
1✔
263
  }
1✔
264

265
  /**
266
   * Adds the group by property.
267
   *
268
   * @param name
269
   *          the name
270
   */
271
  public void addGroupByProperty(String name) {
272
    if (groupByProps == null) {
1!
273
      groupByProps = new HashSet<>();
1✔
274
    }
275
    groupByProps.add(name);
1✔
276
  }
1✔
277

278
  /**
279
   * Checks for group by.
280
   *
281
   * @return true, if successful
282
   */
283
  public boolean hasGroupBy() {
284
    return groupByProps != null && groupByProps.size() > 0;
1!
285
  }
286

287
  /**
288
   * Group by props.
289
   *
290
   * @return the iterator
291
   */
292
  public Iterator groupByProps() {
293
    return groupByProps.iterator();
1✔
294
  }
295

296
  /**
297
   * Adds the nested result mappings.
298
   *
299
   * @param mapping
300
   *          the mapping
301
   */
302
  public void addNestedResultMappings(ResultMapping mapping) {
303
    if (nestedResultMappings == null) {
1✔
304
      nestedResultMappings = new ArrayList<>();
1✔
305
    }
306
    nestedResultMappings.add(mapping);
1✔
307
  }
1✔
308

309
  /**
310
   * Gets the nested result mappings.
311
   *
312
   * @return the nested result mappings
313
   */
314
  public List getNestedResultMappings() {
315
    return nestedResultMappings;
1✔
316
  }
317

318
  /**
319
   * Gets the result mappings.
320
   *
321
   * @return the result mappings
322
   */
323
  public ResultMapping[] getResultMappings() {
324
    if (allowRemapping) {
1✔
325
      return (ResultMapping[]) remappableResultMappings.get();
1✔
326
    }
327
    return resultMappings;
1✔
328
  }
329

330
  /**
331
   * Sets the discriminator.
332
   *
333
   * @param discriminator
334
   *          the new discriminator
335
   */
336
  public void setDiscriminator(Discriminator discriminator) {
337
    if (this.discriminator != null) {
1!
UNCOV
338
      throw new SqlMapException("A discriminator may only be set once per result map.");
×
339
    }
340
    this.discriminator = discriminator;
1✔
341
  }
1✔
342

343
  /**
344
   * Gets the discriminator.
345
   *
346
   * @return the discriminator
347
   */
348
  public Discriminator getDiscriminator() {
349
    return discriminator;
1✔
350
  }
351

352
  /**
353
   * Resolve sub map.
354
   *
355
   * @param statementScope
356
   *          the statement scope
357
   * @param rs
358
   *          the rs
359
   *
360
   * @return the result map
361
   *
362
   * @throws SQLException
363
   *           the SQL exception
364
   */
365
  public ResultMap resolveSubMap(StatementScope statementScope, ResultSet rs) throws SQLException {
366
    ResultMap subMap = this;
1✔
367
    if (discriminator != null) {
1✔
368
      ResultMapping mapping = discriminator.getResultMapping();
1✔
369
      Object value = getPrimitiveResultMappingValue(rs, mapping);
1✔
370
      if (value == null) {
1!
UNCOV
371
        value = doNullMapping(value, mapping);
×
372
      }
373
      subMap = discriminator.getSubMap(String.valueOf(value));
1✔
374
      if (subMap == null) {
1✔
375
        subMap = this;
1✔
376
      } else if (subMap != this) {
1!
377
        subMap = subMap.resolveSubMap(statementScope, rs);
1✔
378
      }
379
    }
380
    return subMap;
1✔
381
  }
382

383
  /**
384
   * Setter for a list of the individual ResultMapping objects.
385
   *
386
   * @param resultMappingList
387
   *          - the list
388
   */
389
  public void setResultMappingList(List resultMappingList) {
390
    if (allowRemapping) {
1✔
391
      this.remappableResultMappings.set(resultMappingList.toArray(new ResultMapping[resultMappingList.size()]));
1✔
392
    } else {
393
      this.resultMappings = (ResultMapping[]) resultMappingList.toArray(new ResultMapping[resultMappingList.size()]);
1✔
394
    }
395

396
    Map props = new HashMap<>();
1✔
397
    props.put("map", this);
1✔
398
    dataExchange = getDelegate().getDataExchangeFactory().getDataExchangeForClass(resultClass);
1✔
399
    dataExchange.initialize(props);
1✔
400
  }
1✔
401

402
  /**
403
   * Getter for the number of ResultMapping objects.
404
   *
405
   * @return - the count
406
   */
407
  public int getResultCount() {
UNCOV
408
    return this.getResultMappings().length;
×
409
  }
410

411
  /**
412
   * Read a row from a resultset and map results to an array.
413
   *
414
   * @param statementScope
415
   *          scope of the request
416
   * @param rs
417
   *          ResultSet to read from
418
   *
419
   * @return row read as an array of column values.
420
   *
421
   * @throws SQLException
422
   *           the SQL exception
423
   */
424
  public Object[] getResults(StatementScope statementScope, ResultSet rs) throws SQLException {
425
    ErrorContext errorContext = statementScope.getErrorContext();
1✔
426
    errorContext.setActivity("applying a result map");
1✔
427
    errorContext.setObjectId(this.getId());
1✔
428
    errorContext.setResource(this.getResource());
1✔
429
    errorContext.setMoreInfo("Check the result map.");
1✔
430

431
    boolean foundData = false;
1✔
432
    Object[] columnValues = new Object[getResultMappings().length];
1✔
433
    for (int i = 0; i < getResultMappings().length; i++) {
1✔
434
      ResultMapping mapping = getResultMappings()[i];
1✔
435
      errorContext.setMoreInfo(mapping.getErrorString());
1✔
436
      if (mapping.getStatementName() != null) {
1✔
437
        if (resultClass == null) {
1!
UNCOV
438
          throw new SqlMapException(
×
UNCOV
439
              "The result class was null when trying to get results for ResultMap named " + getId() + ".");
×
440
        }
441
        if (Map.class.isAssignableFrom(resultClass)) {
1!
442
          Class javaType = mapping.getJavaType();
×
UNCOV
443
          if (javaType == null) {
×
444
            javaType = Object.class;
×
445
          }
UNCOV
446
          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType);
×
447
        } else if (DomTypeMarker.class.isAssignableFrom(resultClass)) {
1✔
448
          Class javaType = mapping.getJavaType();
1✔
449
          if (javaType == null) {
1✔
450
            javaType = DomTypeMarker.class;
1✔
451
          }
452
          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, javaType);
1✔
453
        } else {
1✔
454
          Probe p = ProbeFactory.getProbe(resultClass);
1✔
455
          Class type = p.getPropertyTypeForSetter(resultClass, mapping.getPropertyName());
1✔
456
          columnValues[i] = getNestedSelectMappingValue(statementScope, rs, mapping, type);
1✔
457
        }
458
        foundData = foundData || columnValues[i] != null;
1!
459
      } else if (mapping.getNestedResultMapName() == null) {
1✔
460
        columnValues[i] = getPrimitiveResultMappingValue(rs, mapping);
1✔
461
        if (columnValues[i] == null) {
1✔
462
          columnValues[i] = doNullMapping(columnValues[i], mapping);
1✔
463
        } else {
464
          foundData = true;
1✔
465
        }
466
      }
467
    }
468

469
    statementScope.setRowDataFound(foundData);
1✔
470

471
    return columnValues;
1✔
472
  }
473

474
  /**
475
   * Sets the result object values.
476
   *
477
   * @param statementScope
478
   *          the statement scope
479
   * @param resultObject
480
   *          the result object
481
   * @param values
482
   *          the values
483
   *
484
   * @return the object
485
   */
486
  public Object setResultObjectValues(StatementScope statementScope, Object resultObject, Object[] values) {
487
    final String previousNestedKey = statementScope.getCurrentNestedKey();
1✔
488
    String ukey = (String) getUniqueKey(statementScope.getCurrentNestedKey(), values);
1✔
489
    Map uniqueKeys = statementScope.getUniqueKeys(this);
1✔
490
    statementScope.setCurrentNestedKey(ukey);
1✔
491
    if (uniqueKeys != null && uniqueKeys.containsKey(ukey)) {
1✔
492
      // Unique key is already known, so get the existing result object and process additional
493
      // results.
494
      resultObject = uniqueKeys.get(ukey);
1✔
495
      applyNestedResultMap(statementScope, resultObject, values);
1✔
496
      resultObject = NO_VALUE;
1✔
497
    } else if (ukey == null || uniqueKeys == null || !uniqueKeys.containsKey(ukey)) {
1!
498
      // Unique key is NOT known, so create a new result object and then process additional
499
      // results.
500
      resultObject = dataExchange.setData(statementScope, this, resultObject, values);
1✔
501
      // Lazy init key set, only if we're grouped by something (i.e. ukey != null)
502
      if (ukey != null) {
1✔
503
        if (uniqueKeys == null) {
1✔
504
          uniqueKeys = new HashMap<>();
1✔
505
          statementScope.setUniqueKeys(this, uniqueKeys);
1✔
506
        }
507
        uniqueKeys.put(ukey, resultObject);
1✔
508
      }
509
      applyNestedResultMap(statementScope, resultObject, values);
1✔
510
    } else {
511
      // Otherwise, we don't care about these results.
UNCOV
512
      resultObject = NO_VALUE;
×
513
    }
514

515
    statementScope.setCurrentNestedKey(previousNestedKey);
1✔
516
    return resultObject;
1✔
517
  }
518

519
  /**
520
   * Apply nested result map.
521
   *
522
   * @param statementScope
523
   *          the statement scope
524
   * @param resultObject
525
   *          the result object
526
   * @param values
527
   *          the values
528
   */
529
  private void applyNestedResultMap(StatementScope statementScope, Object resultObject, Object[] values) {
530
    if (resultObject != null && resultObject != NO_VALUE && nestedResultMappings != null) {
1!
531
      for (Object nestedResultMapping : nestedResultMappings) {
1✔
532
        ResultMapping resultMapping = (ResultMapping) nestedResultMapping;
1✔
533
        setNestedResultMappingValue(resultMapping, statementScope, resultObject, values);
1✔
534
      }
1✔
535
    }
536
  }
1✔
537

538
  /**
539
   * Some changes in this method for IBATIS-225:
540
   * <ul>
541
   * <li>We no longer require the nested property to be a collection. This will allow reuses of resultMaps on 1:1
542
   * relationships</li>
543
   * <li>If the nested property is not a collection, then it will be created/replaced by the values generated from the
544
   * current row.</li>
545
   * </ul>
546
   *
547
   * @param mapping
548
   *          the mapping
549
   * @param statementScope
550
   *          the statement scope
551
   * @param resultObject
552
   *          the result object
553
   * @param values
554
   *          the values
555
   */
556
  protected void setNestedResultMappingValue(ResultMapping mapping, StatementScope statementScope, Object resultObject,
557
      Object[] values) {
558
    try {
559

560
      String resultMapName = mapping.getNestedResultMapName();
1✔
561
      ResultMap resultMap = getDelegate().getResultMap(resultMapName);
1✔
562
      // get the discriminated submap if it exists
563
      resultMap = resultMap.resolveSubMap(statementScope, statementScope.getResultSet());
1✔
564

565
      Class type = mapping.getJavaType();
1✔
566
      String propertyName = mapping.getPropertyName();
1✔
567

568
      Object obj = PROBE.getObject(resultObject, propertyName);
1✔
569

570
      if (obj == null) {
1✔
571
        if (type == null) {
1!
572
          type = PROBE.getPropertyTypeForSetter(resultObject, propertyName);
1✔
573
        }
574

575
        try {
576
          // create the object if is it a Collection. If not a Collection
577
          // then we will just set the property to the object created
578
          // in processing the nested result map
579
          if (Collection.class.isAssignableFrom(type)) {
1✔
580
            obj = ResultObjectFactoryUtil.createObjectThroughFactory(type);
1✔
581
            PROBE.setObject(resultObject, propertyName, obj);
1✔
582
          }
583
        } catch (Exception e) {
×
584
          throw new SqlMapException(
×
585
              "Error instantiating collection property for mapping '" + mapping.getPropertyName() + "'.  Cause: " + e,
×
586
              e);
587
        }
1✔
588
      }
589

590
      // JIRA 375
591
      // "Provide a way for not creating items from nested ResultMaps when the items contain only null values"
592
      boolean subResultObjectAbsent = false;
1✔
593
      if (mapping.getNotNullColumn() != null
1!
594
          && statementScope.getResultSet().getObject(mapping.getNotNullColumn()) == null) {
×
595
        subResultObjectAbsent = true;
×
596
      }
597
      if (!subResultObjectAbsent) {
1!
598
        values = resultMap.getResults(statementScope, statementScope.getResultSet());
1✔
599
        if (statementScope.isRowDataFound()) {
1✔
600
          Object o = resultMap.setResultObjectValues(statementScope, null, values);
1✔
601
          if (o != NO_VALUE) {
1✔
602
            if (obj instanceof Collection) {
1✔
603
              ((Collection) obj).add(o);
1✔
604
            } else {
605
              PROBE.setObject(resultObject, propertyName, o);
1✔
606
            }
607
          }
608
        }
609
      }
UNCOV
610
    } catch (SQLException e) {
×
611
      throw new SqlMapException(
×
612
          "Error getting nested result map values for '" + mapping.getPropertyName() + "'.  Cause: " + e, e);
×
613
    }
1✔
614
  }
1✔
615

616
  /**
617
   * Gets the nested select mapping value.
618
   *
619
   * @param statementScope
620
   *          the statement scope
621
   * @param rs
622
   *          the rs
623
   * @param mapping
624
   *          the mapping
625
   * @param targetType
626
   *          the target type
627
   *
628
   * @return the nested select mapping value
629
   *
630
   * @throws SQLException
631
   *           the SQL exception
632
   */
633
  protected Object getNestedSelectMappingValue(StatementScope statementScope, ResultSet rs, ResultMapping mapping,
634
      Class targetType) throws SQLException {
635
    try {
636
      TypeHandlerFactory typeHandlerFactory = getDelegate().getTypeHandlerFactory();
1✔
637

638
      String statementName = mapping.getStatementName();
1✔
639
      SqlMapClientImpl client = (SqlMapClientImpl) statementScope.getSession().getSqlMapClient();
1✔
640

641
      MappedStatement mappedStatement = client.getMappedStatement(statementName);
1✔
642
      Class parameterType = mappedStatement.getParameterClass();
1✔
643
      Object parameterObject = null;
1✔
644

645
      if (parameterType == null) {
1!
UNCOV
646
        parameterObject = prepareBeanParameterObject(statementScope, rs, mapping, parameterType);
×
647
      } else if (typeHandlerFactory.hasTypeHandler(parameterType)) {
1✔
648
        parameterObject = preparePrimitiveParameterObject(rs, mapping, parameterType);
1✔
649
      } else if (DomTypeMarker.class.isAssignableFrom(parameterType)) {
1✔
650
        parameterObject = prepareDomParameterObject(rs, mapping);
1✔
651
      } else {
652
        parameterObject = prepareBeanParameterObject(statementScope, rs, mapping, parameterType);
1✔
653
      }
654

655
      Object result = null;
1✔
656
      if (parameterObject != null) {
1!
657

658
        Sql sql = mappedStatement.getSql();
1✔
659
        ResultMap resultMap = sql.getResultMap(statementScope, parameterObject);
1✔
660
        Class resultClass = resultMap.getResultClass();
1✔
661

662
        if (resultClass != null && !DomTypeMarker.class.isAssignableFrom(targetType)) {
1!
663
          if (DomCollectionTypeMarker.class.isAssignableFrom(resultClass)) {
1!
UNCOV
664
            targetType = DomCollectionTypeMarker.class;
×
665
          } else if (DomTypeMarker.class.isAssignableFrom(resultClass)) {
1!
UNCOV
666
            targetType = DomTypeMarker.class;
×
667
          }
668
        }
669

670
        result = ResultLoader.loadResult(client, statementName, parameterObject, targetType);
1✔
671

672
        String nullValue = mapping.getNullValue();
1✔
673
        if (result == null && nullValue != null) {
1!
UNCOV
674
          TypeHandler typeHandler = typeHandlerFactory.getTypeHandler(targetType);
×
UNCOV
675
          if (typeHandler != null) {
×
UNCOV
676
            result = typeHandler.valueOf(nullValue);
×
677
          }
678
        }
679
      }
680
      return result;
1✔
UNCOV
681
    } catch (InstantiationException | IllegalAccessException e) {
×
UNCOV
682
      throw new NestedSQLException("Error setting nested bean property.  Cause: " + e, e);
×
683
    }
684

685
  }
686

687
  /**
688
   * Prepare primitive parameter object.
689
   *
690
   * @param rs
691
   *          the rs
692
   * @param mapping
693
   *          the mapping
694
   * @param parameterType
695
   *          the parameter type
696
   *
697
   * @return the object
698
   *
699
   * @throws SQLException
700
   *           the SQL exception
701
   */
702
  private Object preparePrimitiveParameterObject(ResultSet rs, ResultMapping mapping, Class parameterType)
703
      throws SQLException {
704
    TypeHandlerFactory typeHandlerFactory = getDelegate().getTypeHandlerFactory();
1✔
705
    TypeHandler th = typeHandlerFactory.getTypeHandler(parameterType);
1✔
706
    return th.getResult(rs, mapping.getColumnName());
1✔
707
  }
708

709
  /**
710
   * New document.
711
   *
712
   * @param root
713
   *          the root
714
   *
715
   * @return the document
716
   */
717
  private Document newDocument(String root) {
718
    try {
719
      Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
1✔
720
      doc.appendChild(doc.createElement(root));
1✔
721
      return doc;
1✔
UNCOV
722
    } catch (ParserConfigurationException e) {
×
UNCOV
723
      throw new RuntimeException("Error creating XML document.  Cause: " + e);
×
724
    }
725
  }
726

727
  /**
728
   * Prepare dom parameter object.
729
   *
730
   * @param rs
731
   *          the rs
732
   * @param mapping
733
   *          the mapping
734
   *
735
   * @return the object
736
   *
737
   * @throws SQLException
738
   *           the SQL exception
739
   */
740
  private Object prepareDomParameterObject(ResultSet rs, ResultMapping mapping) throws SQLException {
741
    TypeHandlerFactory typeHandlerFactory = getDelegate().getTypeHandlerFactory();
1✔
742

743
    Document doc = newDocument("parameter");
1✔
744
    Probe probe = ProbeFactory.getProbe(doc);
1✔
745

746
    String complexName = mapping.getColumnName();
1✔
747

748
    TypeHandler stringTypeHandler = typeHandlerFactory.getTypeHandler(String.class);
1✔
749
    if (complexName.indexOf('=') > -1) {
1!
750
      // old 1.x style multiple params
751
      StringTokenizer parser = new StringTokenizer(complexName, "{}=, ", false);
1✔
752
      while (parser.hasMoreTokens()) {
1✔
753
        String propName = parser.nextToken();
1✔
754
        String colName = parser.nextToken();
1✔
755
        Object propValue = stringTypeHandler.getResult(rs, colName);
1✔
756
        probe.setObject(doc, propName, propValue.toString());
1✔
757
      }
1✔
758
    } else {
1✔
759
      // single param
UNCOV
760
      Object propValue = stringTypeHandler.getResult(rs, complexName);
×
UNCOV
761
      probe.setObject(doc, "value", propValue.toString());
×
762
    }
763

764
    return doc;
1✔
765
  }
766

767
  /**
768
   * Prepare bean parameter object.
769
   *
770
   * @param statementScope
771
   *          the statement scope
772
   * @param rs
773
   *          the rs
774
   * @param mapping
775
   *          the mapping
776
   * @param parameterType
777
   *          the parameter type
778
   *
779
   * @return the object
780
   *
781
   * @throws InstantiationException
782
   *           the instantiation exception
783
   * @throws IllegalAccessException
784
   *           the illegal access exception
785
   * @throws SQLException
786
   *           the SQL exception
787
   */
788
  private Object prepareBeanParameterObject(StatementScope statementScope, ResultSet rs, ResultMapping mapping,
789
      Class parameterType) throws InstantiationException, IllegalAccessException, SQLException {
790
    TypeHandlerFactory typeHandlerFactory = getDelegate().getTypeHandlerFactory();
1✔
791

792
    Object parameterObject;
793
    if (parameterType == null) {
1!
UNCOV
794
      parameterObject = new HashMap<>();
×
795
    } else {
796
      parameterObject = ResultObjectFactoryUtil.createObjectThroughFactory(parameterType);
1✔
797
    }
798
    String complexName = mapping.getColumnName();
1✔
799

800
    if (complexName.indexOf('=') > -1 || complexName.indexOf(',') > -1) {
1!
801
      StringTokenizer parser = new StringTokenizer(complexName, "{}=, ", false);
1✔
802
      while (parser.hasMoreTokens()) {
1✔
803
        String propName = parser.nextToken();
1✔
804
        String colName = parser.nextToken();
1✔
805
        Class propType = PROBE.getPropertyTypeForSetter(parameterObject, propName);
1✔
806
        TypeHandler propTypeHandler = typeHandlerFactory.getTypeHandler(propType);
1✔
807
        Object propValue = propTypeHandler.getResult(rs, colName);
1✔
808
        PROBE.setObject(parameterObject, propName, propValue);
1✔
809
      }
1✔
810
    } else {
1✔
811
      // single param
UNCOV
812
      TypeHandler propTypeHandler = typeHandlerFactory.getTypeHandler(parameterType);
×
UNCOV
813
      if (propTypeHandler == null) {
×
UNCOV
814
        propTypeHandler = typeHandlerFactory.getUnkownTypeHandler();
×
815
      }
816
      parameterObject = propTypeHandler.getResult(rs, complexName);
×
817
    }
818

819
    return parameterObject;
1✔
820
  }
821

822
  /**
823
   * Gets the primitive result mapping value.
824
   *
825
   * @param rs
826
   *          the rs
827
   * @param mapping
828
   *          the mapping
829
   *
830
   * @return the primitive result mapping value
831
   *
832
   * @throws SQLException
833
   *           the SQL exception
834
   */
835
  protected Object getPrimitiveResultMappingValue(ResultSet rs, ResultMapping mapping) throws SQLException {
836
    Object value = null;
1✔
837
    TypeHandler typeHandler = mapping.getTypeHandler();
1✔
838
    if (typeHandler == null) {
1!
UNCOV
839
      throw new SqlMapException("No type handler could be found to map the property '" + mapping.getPropertyName()
×
UNCOV
840
          + "' to the column '" + mapping.getColumnName()
×
841
          + "'.  One or both of the types, or the combination of types is not supported.");
842
    }
843
    String columnName = mapping.getColumnName();
1✔
844
    int columnIndex = mapping.getColumnIndex();
1✔
845
    if (columnName == null) {
1!
UNCOV
846
      value = typeHandler.getResult(rs, columnIndex);
×
847
    } else {
848
      value = typeHandler.getResult(rs, columnName);
1✔
849
    }
850
    return value;
1✔
851
  }
852

853
  /**
854
   * Do null mapping.
855
   *
856
   * @param value
857
   *          the value
858
   * @param mapping
859
   *          the mapping
860
   *
861
   * @return the object
862
   *
863
   * @throws SqlMapException
864
   *           the sql map exception
865
   */
866
  protected Object doNullMapping(Object value, ResultMapping mapping) throws SqlMapException {
867
    if (value != null) {
1!
UNCOV
868
      return value;
×
869
    }
870

871
    TypeHandler typeHandler = mapping.getTypeHandler();
1✔
872
    if (typeHandler != null) {
1!
873
      String nullValue = mapping.getNullValue();
1✔
874
      if (nullValue != null) {
1✔
875
        value = typeHandler.valueOf(nullValue);
1✔
876
      }
877
      return value;
1✔
878
    }
879
    throw new SqlMapException(
×
880
        "No type handler could be found to map the property '" + mapping.getPropertyName() + "' to the column '"
×
UNCOV
881
            + mapping.getColumnName() + "'.  One or both of the types, or the combination of types is not supported.");
×
882
  }
883
}
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