Java MyBatis在Map.Entry和Map.entrySet()的集合上出错

Java MyBatis在Map.Entry和Map.entrySet()的集合上出错,java,dictionary,mybatis,Java,Dictionary,Mybatis,假设我们有MyBatis 3.3.0和MyBatis Spring 1.2.3以及一个简单的select查询 <select id="testSelect" parameterType="map" resultType="Integer"> select 1 from dual where <foreach collection="properties" index="index" item="item" separator=" and ">

假设我们有MyBatis 3.3.0和MyBatis Spring 1.2.3以及一个简单的select查询

<select id="testSelect" parameterType="map" resultType="Integer">
    select 1 from dual where
    <foreach collection="properties" index="index" item="item" separator=" and ">
        1 = #{id} AND 'a' = #{item.key,jdbcType=VARCHAR} AND 'b' = #{item.value,jdbcType=VARCHAR}
    </foreach>
</select>
…我们用这种测试方法测试它

Integer testSelect(Map<String, Object> arguments);
@Test
public void test_for_bug() {

    final Map<String, Object> parameters = new HashMap<>();
    parameters.put("id", 1);

    final Map<String, String> entries = new HashMap<>();
    entries.put("a", "b");
    parameters.put("properties", entries.entrySet());

    final Integer result = this.testMapper.testSelect(parameters);

    assertThat(result).isEqualTo(1);

}
……还有

@Test
public void test_for_bug() {

    final Map<String, String> entries = new HashMap<>();
    entries.put("a", "b");

    final Map<String, Object> parameters = new HashMap<>();
    parameters.put("entry", entries.entrySet().iterator().next());

    final Integer result = this.testMapper.testSelect(parameters);

    assertThat(result).isEqualTo(1);

}
…有效


有人知道Map.EntrySet有什么问题吗?有没有机会把它修好?当然,创建一个变通方法是很容易的,但我认为不需要它。

您只需传递参数map而不是map.entrySet,如下所示

parameters.put("properties", entries);
这样称呼你的mybatis

<select id="testSelect" parameterType="map" resultType="Integer">
    select 1 from dual where
    <foreach collection="properties.entrySet()" index="index" item="item" separator=" and ">
        1 = #{id} AND 'a' = #{item.key,jdbcType=VARCHAR} AND 'b' = #{item.value,jdbcType=VARCHAR}
    </foreach>
</select> 

只需传递参数map而不是map.entrySet,如下所示

parameters.put("properties", entries);
这样称呼你的mybatis

<select id="testSelect" parameterType="map" resultType="Integer">
    select 1 from dual where
    <foreach collection="properties.entrySet()" index="index" item="item" separator=" and ">
        1 = #{id} AND 'a' = #{item.key,jdbcType=VARCHAR} AND 'b' = #{item.value,jdbcType=VARCHAR}
    </foreach>
</select> 

由于开发人员在几个版本之前做了一些更改,因此处理已提交的此文档更新的正确方法似乎如下所示:

<select id="testSelect" parameterType="map" resultType="Integer">
    select 1 from dual where
    <foreach collection="properties" index="index" item="item" separator=" and ">
        1 = #{id} AND 'a' = #{index,jdbcType=VARCHAR} AND 'b' = #{item,jdbcType=VARCHAR}
    </foreach>
</select>
原因是,对于Iterables/数组、映射和可迭代对象,其行为有点不同:

对于Iterable或数组,index是当前迭代的编号,item是在此迭代中从Iterable检索到的元素。 对于Map或Iterable,索引是当前条目的键,item是当前条目的值
这解释了为什么映射的item.value实际上会导致String.value该值已经是一个字符串-它有一个名为value的私有字符数组成员,因此MyBatis正在尝试访问String.value-但失败,因为字符数组不是映射类型。

似乎处理已提交的文档更新的正确方法如下,因为开发人员在几个版本之前做了一些更改:

<select id="testSelect" parameterType="map" resultType="Integer">
    select 1 from dual where
    <foreach collection="properties" index="index" item="item" separator=" and ">
        1 = #{id} AND 'a' = #{index,jdbcType=VARCHAR} AND 'b' = #{item,jdbcType=VARCHAR}
    </foreach>
</select>
原因是,对于Iterables/数组、映射和可迭代对象,其行为有点不同:

对于Iterable或数组,index是当前迭代的编号,item是在此迭代中从Iterable检索到的元素。 对于Map或Iterable,索引是当前条目的键,item是当前条目的值
这解释了为什么映射的item.value实际上会导致String.value该值已经是一个字符串,它有一个名为value的私有字符数组成员,因此MyBatis尝试访问String.value,但失败了,因为字符数组不是映射类型。

为什么要使用parameters.putproperties,entries.entrySet?在这种情况下,因为这是一种从映射中给出一组键值对的简单方法。。。换句话说:为什么不呢?或者手动将地图转换为一组具有键/值属性的对象。。。从技术上讲,我没有,因为我没有编写原始代码,我只是在那里发现了错误。为什么要使用parameters.putproperties,entries.entrySet?在这种情况下,因为这是一种从映射中给出一组键值对的简单方法。。。换句话说:为什么不呢?或者手动将地图转换为一组具有键/值属性的对象。。。从技术上讲,我没有,因为我没有编写原始代码,我只是在那里发现了错误。你真的试过了吗?因为对我来说,这根本改变不了什么。同样的问题:属性的参数映射上的类型处理程序为null…您的mybatis版本是什么?自3.2x版以来不支持此解决方案。检查此问题尝试使用3.3.1,可能是同一个问题,对。您确实尝试过吗?因为对我来说,这根本改变不了什么。同样的问题:属性的参数映射上的类型处理程序为null…您的mybatis版本是什么?自3.2x版以来不支持此解决方案。检查此问题尝试使用3.3.1,可能是相同的问题,正确。