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

mybatis / mybatis-3 / 2680

27 Jan 2025 11:09PM UTC coverage: 87.217% (+0.006%) from 87.211%
2680

push

github

web-flow
Merge pull request #2760 from harawata/bind-in-foreach

Handle `<bind>` correctly inside `<foreach>`

3681 of 4487 branches covered (82.04%)

143 of 153 new or added lines in 12 files covered. (93.46%)

1 existing line in 1 file now uncovered.

9668 of 11085 relevant lines covered (87.22%)

0.87 hits per line

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

87.18
/src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.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.builder;
17

18
import java.util.List;
19
import java.util.Map;
20

21
import org.apache.ibatis.mapping.ParameterMapping;
22
import org.apache.ibatis.mapping.ParameterMode;
23
import org.apache.ibatis.parsing.TokenHandler;
24
import org.apache.ibatis.reflection.MetaClass;
25
import org.apache.ibatis.reflection.MetaObject;
26
import org.apache.ibatis.reflection.property.PropertyTokenizer;
27
import org.apache.ibatis.session.Configuration;
28
import org.apache.ibatis.type.JdbcType;
29

30
public class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
31

32
  private static final String PARAMETER_PROPERTIES = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
33
  private final List<ParameterMapping> parameterMappings;
34
  private final Class<?> parameterType;
35
  private final MetaObject metaParameters;
36
  private final Object parameterObject;
37
  private final boolean paramExists;
38

39
  public ParameterMappingTokenHandler(List<ParameterMapping> parameterMappings, Configuration configuration,
40
      Object parameterObject, Class<?> parameterType, Map<String, Object> additionalParameters, boolean paramExists) {
41
    super(configuration);
1✔
42
    this.parameterType = parameterObject == null ? (parameterType == null ? Object.class : parameterType)
1✔
43
        : parameterObject.getClass();
1✔
44
    this.metaParameters = configuration.newMetaObject(additionalParameters);
1✔
45
    this.parameterObject = parameterObject;
1✔
46
    this.paramExists = paramExists;
1✔
47
    this.parameterMappings = parameterMappings;
1✔
48
  }
1✔
49

50
  public ParameterMappingTokenHandler(List<ParameterMapping> parameterMappings, Configuration configuration,
51
      Class<?> parameterType, Map<String, Object> additionalParameters) {
52
    super(configuration);
1✔
53
    this.parameterType = parameterType;
1✔
54
    this.metaParameters = configuration.newMetaObject(additionalParameters);
1✔
55
    this.parameterObject = null;
1✔
56
    this.paramExists = false;
1✔
57
    this.parameterMappings = parameterMappings;
1✔
58
  }
1✔
59

60
  public List<ParameterMapping> getParameterMappings() {
61
    return parameterMappings;
1✔
62
  }
63

64
  @Override
65
  public String handleToken(String content) {
66
    parameterMappings.add(buildParameterMapping(content));
1✔
67
    return "?";
1✔
68
  }
69

70
  private ParameterMapping buildParameterMapping(String content) {
71
    Map<String, String> propertiesMap = parseParameterMapping(content);
1✔
72
    String property = propertiesMap.get("property");
1✔
73
    PropertyTokenizer propertyTokenizer = new PropertyTokenizer(property);
1✔
74
    Class<?> propertyType;
75
    if (metaParameters.hasGetter(propertyTokenizer.getName())) { // issue #448 get type from additional params
1✔
76
      propertyType = metaParameters.getGetterType(property);
1✔
77
    } else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
1✔
78
      propertyType = parameterType;
1✔
79
    } else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
1!
NEW
80
      propertyType = java.sql.ResultSet.class;
×
81
    } else if (property == null || Map.class.isAssignableFrom(parameterType)) {
1!
82
      propertyType = Object.class;
1✔
83
    } else {
84
      MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
1✔
85
      if (metaClass.hasGetter(property)) {
1✔
86
        propertyType = metaClass.getGetterType(property);
1✔
87
      } else {
88
        propertyType = Object.class;
1✔
89
      }
90
    }
91
    ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
1✔
92
    Class<?> javaType = propertyType;
1✔
93
    String typeHandlerAlias = null;
1✔
94
    ParameterMode mode = null;
1✔
95
    for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
1✔
96
      String name = entry.getKey();
1✔
97
      String value = entry.getValue();
1✔
98
      if ("javaType".equals(name)) {
1✔
99
        javaType = resolveClass(value);
1✔
100
        builder.javaType(javaType);
1✔
101
      } else if ("jdbcType".equals(name)) {
1✔
102
        builder.jdbcType(resolveJdbcType(value));
1✔
103
      } else if ("mode".equals(name)) {
1✔
104
        mode = resolveParameterMode(value);
1✔
105
        builder.mode(mode);
1✔
106
      } else if ("numericScale".equals(name)) {
1!
NEW
107
        builder.numericScale(Integer.valueOf(value));
×
108
      } else if ("resultMap".equals(name)) {
1!
NEW
109
        builder.resultMapId(value);
×
110
      } else if ("typeHandler".equals(name)) {
1✔
111
        typeHandlerAlias = value;
1✔
112
      } else if ("jdbcTypeName".equals(name)) {
1!
NEW
113
        builder.jdbcTypeName(value);
×
114
      } else if ("property".equals(name)) {
1!
115
        // Do Nothing
NEW
116
      } else if ("expression".equals(name)) {
×
NEW
117
        throw new BuilderException("Expression based parameters are not supported yet");
×
118
      } else {
NEW
119
        throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content
×
120
            + "}.  Valid properties are " + PARAMETER_PROPERTIES);
121
      }
122
    }
1✔
123
    if (typeHandlerAlias != null) {
1✔
124
      builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
1✔
125
    }
126
    if (!ParameterMode.OUT.equals(mode) && paramExists) {
1✔
127
      if (metaParameters.hasGetter(propertyTokenizer.getName())) {
1✔
128
        builder.value(metaParameters.getValue(property));
1✔
129
      } else if (parameterObject == null) {
1!
NEW
130
        builder.value(null);
×
131
      } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
1✔
132
        builder.value(parameterObject);
1✔
133
      } else {
134
        MetaObject metaObject = configuration.newMetaObject(parameterObject);
1✔
135
        builder.value(metaObject.getValue(property));
1✔
136
      }
137
    }
138
    return builder.build();
1✔
139
  }
140

141
  private Map<String, String> parseParameterMapping(String content) {
142
    try {
143
      return new ParameterExpression(content);
1✔
NEW
144
    } catch (BuilderException ex) {
×
NEW
145
      throw ex;
×
146
    } catch (Exception ex) {
1✔
147
      throw new BuilderException("Parsing error was found in mapping #{" + content
1✔
148
          + "}.  Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
149
    }
150
  }
151
}
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