mybatisjava-17oracle19cspring-mybatis

Using Map in where clause in @Select query, giving error parameter not found


@Select("""
       SELECT CURRENCY_CD,COUNTRY_CD,FEE_RATE_VAL FROM FEE
               WHERE (COUNTRY_CD, CURRENCY_CD) IN               
       <foreach item="currencyCd" index="countryCd"    collection="countryCurrencyCodes.entrySet()" separator="," close="">
                    (#{countryCd},#{currencyCd})
       </foreach>
       """)
 @Results(value = {
    @Result(property = "currencyCd", column = "CURRENCY_CD"),
    @Result(property = "countryCd", column = "COUNTRY_CD"),
    @Result(property = "feeRateValue", column = "FEE_RATE_VAL")
 })
 List<Fee> getFeeOf(@Param("countryCurrencyCodes") Map<String, String> countryCurrencyCodes);

Getting

BindingException: Parameter 'countryCd' not found. Available parameters are [countryCurrencyCodes, param1]

Looks like the syntax in forEach is not correct, i tried without entrySet in foreach, but not working

As per https://mybatis.org/mybatis-3/dynamic-sql.html#foreach When using a Map (or Collection of Map.Entry objects), index will be the key object and item will be the value object.


Solution

  • As mentioned by @ave, if you are using dynamic SQL in an annotated mapper class, you can use a <script> tag.

    Additionally, your IN clause appears to be missing the opening and closing braces around the list of terms.

    Either:

    @Select("""<script>
      SELECT CURRENCY_CD,
             COUNTRY_CD,
             FEE_RATE_VAL
      FROM   FEE
      WHERE  (COUNTRY_CD, CURRENCY_CD) IN (<foreach
                                              item="currencyCd"
                                              index="countryCd"
                                              collection="countryCurrencyCodes.entrySet()"
                                              separator=","
                                              open=""
                                              close="">
               (#{countryCd},#{currencyCd})</foreach>
             )
    </script>""")
    

    or:

    @Select("""<script>
      SELECT CURRENCY_CD,
             COUNTRY_CD,
             FEE_RATE_VAL
      FROM   FEE
      WHERE  <foreach item="currencyCd"
                      index="countryCd"
                      collection="countryCurrencyCodes.entrySet()"
                      separator=","
                      open="(COUNTRY_CD, CURRENCY_CD) IN ("
                      close=")"
             >
               (#{countryCd},#{currencyCd})</foreach>
    </script>""")