您的位置:首页 > 其它

MyBatis 3.3.1 在resultMap中使用association但是没有指定id时的结果集bug

2016-04-15 02:56 573 查看
情景描述:

     resultMap中,如果不指定id列,在映射中同时存在result 和association,如果表中映射过的字段 有连续的非空重复值,那么存在重复值的行不会被加入结果集中。

JavaBean(省略getter  setter):

public class Account {
/** 属性账目编号 */
private Long id;
/** 属性物料编码相关信息 */
private Item item;
/**
* 属性单据类型 0 出库,1入库 ,9:默认(出现9则是异常)
*/
private int type = 9;
/** 属性数量 */
private Double number;
/** 属性归属单位 */
private String department;
/** 属性操作员 */
private String operator;
/** 属性经办人 */
private String handler;
/** 属性出入库原因 */
private String reason;
/** 属性出入库时间 */
private Date optTime;
/** 属性录入时间 */
private Date createTime = Calendar.getInstance().getTime();
/** 属性最后修改时间 */
private Date updateTime;
/** 属性最后修改人 */
private User updater;
}


Mapper:

         
<resultMap type="Account"id="accountMap"autoMapping="true">
<id column ="id" property="id"/>
<result column ="opt_time" property="optTime"/>
<result column ="create_time" property="createTime"/>
<result column ="update_time" property="updateTime"/>
<association property ="item" javaType="Item">
<result column ="item_code" property="code"/>
<result column ="item_name" property="name"/>
<result column ="item_model" property="model"/>
<result column ="unit" property="unit"/>
</association >
</resultMap >


SQL:

     select * from t_account;

在数据库中的查询结果(部分):



1、图中涂红的部分修改过,原来的值与上一行相同,都是 00:00:00。

2、修改以前,程序查询结果中只有id<=38的数据,因为id=37行(以下简称37行)与36行的opt_time字段不同,38行与37行的create_time、update_time字段不同,而39行与38行的这三个映射字段的值完全相同

3、修改后,查询结果中39、40行能显示了,其后的数据不能显示

4、在Mapper中加入id列设置后,所有数据行都能显示了。

建议:在所有的resultMap定义中,最好都指明id列,避免出现类似情况。

追查问题的过程受以下文章启发:

1.MyBatis使用Collection查询多对多或一对多结果集bug

http://www.cnblogs.com/zemliu/archive/2013/08/16/3263053.html

2.mybatis核心组件详解——ResultSetHandler

http://my.oschina.net/lixin91/blog/624772

handleRowValuesForNestedResultMap方法

private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw,
ResultMap resultMap,
ResultHandler<?> resultHandler,
RowBounds rowBounds,
ResultMapping parentMapping) throwsSQLException
{

    final DefaultResultContext <Object> resultContext = new DefaultResultContext<Object>();

    skipRows(rsw.getResultSet(), rowBounds);

    Object rowValue = null;

    while (shouldProcessMoreRows( resultContext, rowBounds )
&& rsw.getResultSet().next())
{

      final ResultMap discriminatedResultMap =
resolveDiscriminatedResultMap(rsw.getResultSet(),resultMap , null);

        // 根据映射字段的值生成缓存key

      final CacheKey rowKey =
createRowKey(discriminatedResultMap, rsw, null);

      // 在缓存中查询key

      Object partialObject = nestedResultObjects.get( rowKey);

      // issue
#577 && #542

      if (mappedStatement.isResultOrdered())
{

        if (partialObject == null && rowValue != null)
{

          nestedResultObjects.clear();

          storeObject( resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

        }

        rowValue =
getRowValue( rsw, discriminatedResultMap, rowKey, null, partialObject);

      } else {

        // 在getRowValue方法中,如果存在缓存就直接取值了

        rowValue =
getRowValue( rsw, discriminatedResultMap, rowKey, null, partialObject);

        if (partialObject == null)
{

          storeObject( resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

        }

      }

    }

    if (rowValue != null && mappedStatement.isResultOrdered()
&& shouldProcessMoreRows(resultContext, rowBounds ))
{

      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());

    }

  }

getRowValue方法:

  private Object
getRowValue(ResultSetWrapper rsw,
ResultMap resultMap,
CacheKey combinedKey,
String columnPrefix,
Object partialObject) throws SQLException
{

    final String resultMapId = resultMap.getId();

    Object resultObject = partialObject;

    if (resultObject != null)
{

      final MetaObject metaObject = configuration.newMetaObject( resultObject);

      putAncestor(resultObject, resultMapId, columnPrefix);

      applyNestedResultMappings (rsw, resultMap , metaObject , columnPrefix , combinedKey, false);

      ancestorObjects.remove( resultMapId);

    } else {

      final ResultLoaderMap lazyLoader = new ResultLoaderMap();

      resultObject =
createResultObject( rsw, resultMap, lazyLoader, columnPrefix);

      if (resultObject != null &&
!typeHandlerRegistry.hasTypeHandler(resultMap .getType()))
{

        final MetaObject metaObject = configuration.newMetaObject( resultObject);

        boolean foundValues =
!resultMap.getConstructorResultMappings().isEmpty();

        if (shouldApplyAutomaticMappings( resultMap, true))
{

          foundValues =
applyAutomaticMappings( rsw, resultMap, metaObject, columnPrefix)
||foundValues;

        }

        foundValues =
applyPropertyMappings( rsw, resultMap, metaObject, lazyLoader, columnPrefix)
|| foundValues;

        putAncestor( resultObject, resultMapId, columnPrefix);

        foundValues = applyNestedResultMappings (rsw, resultMap , metaObject , columnPrefix,combinedKey, true)
|| foundValues;

        ancestorObjects.remove( resultMapId);

        foundValues = lazyLoader.size()
> 0 || foundValues;

        resultObject = foundValues ? resultObject : null;

      }

      if (combinedKey !=
CacheKey. NULL_CACHE_KEY)
{

        nestedResultObjects.put( combinedKey, resultObject);

      }

    }

    return resultObject;

  }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MyBatis bug