Mybatis分组查询分页问题解决记录

2022-04-10  本文已影响0人  haiyong6

利用mybatis分组查询时,比如是一对多的情况下,数据库查出来比如是10条,但是经过分组之后在前端页面展示出来的可能只有7条,这样用mybatis的分页插件显示的分页数量信息就对不上。
如下面这段sql:

<resultMap type="com.ly.mp.project.entities.ecuConfigFile.EcuConfigVO" id="getEcuConfigFileTableGroup">
        <result property="id" column="ecuConfigId"/>
        <result property="ecuConfigId" column="ecuConfigId"/>
        <result property="ecuAddress" column="ecuAddress"/>
        <result property="fileName" column="fileName"/>
        <result property="filePath" column="filePath"/>
        <result property="fileSize" column="fileSize"/>
        <result property="customSettingName" column="customSettingName"/>
        <result property="customSettingMethod" column="customSettingMethod"/>
        <result property="customSettingActionType" column="customSettingActionType"/>
        <result property="customSettingStatus" column="customSettingStatus"/>
        <result property="description" column="description"/>
        <result property="createDate" column="createDate"/>
        <result property="creator" column="creator"/>
        <result property="creatorName" column="creatorName"/>
        <collection property="configTypes" resultMap="getEcuConfigFileTableGroup1"/>
    </resultMap>
    <resultMap type="com.ly.mp.project.entities.ecuConfigFile.ConfigTypeVO" id="getEcuConfigFileTableGroup1">
        <result property="configTypeId" column="configTypeId"/>
        <result property="ecuConfigId" column="ecuConfigId"/>
        <result property="actionType" column="configTypeActionType"/>
        <result property="externalId" column="configTypeExternalId"/>
        <collection property="properties" resultMap="getEcuConfigFileTableGroup2"/>
    </resultMap>
    <resultMap type="com.ly.mp.project.entities.ecuConfigFile.PropertyVO" id="getEcuConfigFileTableGroup2">
        <result property="propertyId" column="propertyId"/>
        <result property="configTypeId" column="configTypeId"/>
        <result property="propertyName" column="propertyName"/>
        <result property="displayName" column="displayName"/>
        <result property="propertyType" column="propertyType"/>
        <result property="propertyOptionsStr" column="propertyOptionsStr"/>
        <result property="description" column="description"/>
        <result property="externalId" column="configPropertyExternalId"/>
    </resultMap>
    <select id="getEcuConfigFileTable" resultMap="getEcuConfigFileTableGroup">
    select f.id ecuConfigId,
        f.ecu_address ecuAddress,
        f.file_name fileName, f.file_path filePath, f.file_size fileSize,
        f.setting_name customSettingName, f.setting_method customSettingMethod, 
        f.action_type customSettingActionType,f.setting_status customSettingStatus,
        f.description,
        date_format(f.create_date, '%Y-%m-%d %H:%i:%s') createDate,
        f.creator, f.creator_name creatorName,
        ft.id configTypeId, 
        ft.ecu_config_id ecuConfigId 
         ft.action_Type configTypeActionType, 
         ft.external_id configTypeExternalId, 
         fp.id propertyId, fp.config_type_id configTypeId, 
         fp.property_name propertyName, fp.display_name displayName, 
         fp.property_type propertyType, fp.property_options propertyOptionsStr,
        fp.description,fp.external_id configPropertyExternalId 
         from t_ecu_config f
         left join t_ecu_config_type ft on f.id = ft.ecu_config_id and f.is_enable = ft.is_enable
        left join t_ecu_config_property fp on ft.id = fp.config_type_id and f.is_enable = fp.is_enable 
        where f.is_enable = 1
        <if test='params.fileName != null and params.fileName != ""'>
        and f.file_name like CONCAT('%',#{params.fileName},'%')
        </if>
        <if test='params.ecuAddress != null and params.ecuAddress != ""'>
        and f.ecu_address = #{params.ecuAddress} 
        </if>
        <if test='params.ids != null and params.ids.size > 0'>
        and f.id in 
            <foreach collection="params.ids" item="id" index="index" open="(" close=")" separator=",">
              #{id}
            </foreach>  
        </if>
        order by f.id desc
    </select>

从上面sql里可以看出,三张表关联 分别是一对多对多的关系,用mybatis的分组查询这样直接查出来是一拖多拖多的json结构,但是因为sql查出来的总条数比如是10条,分组之后,可能是7条,mybatis分页插件依然会认为是10条数据而不是7条数据,该怎么办呢,一度以为是mybatis的分页bug,其实不是。

mybatis针对这种情况,在<collection>标签里包含了可以引入其他子查询语句的select属性和column传递参数属性,下面是改造后的sql:

<resultMap type="com.ly.mp.project.entities.ecuConfigFile.EcuConfigVO" id="getEcuConfigFileTableGroup">
        <result property="id" column="ecuConfigId"/>
        <result property="ecuConfigId" column="ecuConfigId"/>
        <result property="ecuAddress" column="ecuAddress"/>
        <result property="fileName" column="fileName"/>
        <result property="filePath" column="filePath"/>
        <result property="fileSize" column="fileSize"/>
        <result property="customSettingName" column="customSettingName"/>
        <result property="customSettingMethod" column="customSettingMethod"/>
        <result property="customSettingActionType" column="customSettingActionType"/>
        <result property="customSettingStatus" column="customSettingStatus"/>
        <result property="description" column="description"/>
        <result property="createDate" column="createDate"/>
        <result property="creator" column="creator"/>
        <result property="creatorName" column="creatorName"/>
        <collection property="configTypes" select="getEcuConfigTypeByEcuConfigId" column="ecuConfigId"/>
    </resultMap>
    <resultMap type="com.ly.mp.project.entities.ecuConfigFile.ConfigTypeVO" id="getEcuConfigFileTableGroup1">
        <result property="configTypeId" column="configTypeId"/>
        <result property="ecuConfigId" column="ecuConfigId"/>
        <result property="actionType" column="configTypeActionType"/>
        <result property="externalId" column="configTypeExternalId"/>
        <collection property="properties" resultMap="getEcuConfigFileTableGroup2"/>
    </resultMap>
    <resultMap type="com.ly.mp.project.entities.ecuConfigFile.PropertyVO" id="getEcuConfigFileTableGroup2">
        <result property="propertyId" column="propertyId"/>
        <result property="configTypeId" column="configTypeId"/>
        <result property="propertyName" column="propertyName"/>
        <result property="displayName" column="displayName"/>
        <result property="propertyType" column="propertyType"/>
        <result property="propertyOptionsStr" column="propertyOptionsStr"/>
        <result property="description" column="description"/>
        <result property="externalId" column="configPropertyExternalId"/>
    </resultMap>
    <select id="getEcuConfigFileTable" resultMap="getEcuConfigFileTableGroup">
    select f.id ecuConfigId,
        f.ecu_address ecuAddress,
        f.file_name fileName, f.file_path filePath, f.file_size fileSize,
        f.setting_name customSettingName, f.setting_method customSettingMethod, 
        f.action_type customSettingActionType,f.setting_status customSettingStatus,
        f.description,
        date_format(f.create_date, '%Y-%m-%d %H:%i:%s') createDate,
        f.creator, f.creator_name creatorName
        <!-- ft.id configTypeId, -->
        <!-- ft.ecu_config_id ecuConfigId -->
        <!-- ft.action_Type configTypeActionType, -->
        <!-- ft.external_id configTypeExternalId, -->
        <!-- fp.id propertyId, fp.config_type_id configTypeId, -->
        <!-- fp.property_name propertyName, fp.display_name displayName, -->
        <!-- fp.property_type propertyType, fp.property_options propertyOptionsStr,
        fp.description,fp.external_id configPropertyExternalId -->
         from t_ecu_config f
        <!-- left join t_ecu_config_type ft on f.id = ft.ecu_config_id and f.is_enable = ft.is_enable
        left join t_ecu_config_property fp on ft.id = fp.config_type_id and f.is_enable = fp.is_enable -->
        where f.is_enable = 1
        <if test='params.fileName != null and params.fileName != ""'>
        and f.file_name like CONCAT('%',#{params.fileName},'%')
        </if>
        <if test='params.ecuAddress != null and params.ecuAddress != ""'>
        and f.ecu_address = #{params.ecuAddress} 
        </if>
        <if test='params.ids != null and params.ids.size > 0'>
        and f.id in 
            <foreach collection="params.ids" item="id" index="index" open="(" close=")" separator=",">
              #{id}
            </foreach>  
        </if>
        order by f.id desc
    </select>
    
    <select id="getEcuConfigTypeByEcuConfigId" resultMap="getEcuConfigFileTableGroup1">
        select ft.id configTypeId,
        ft.ecu_config_id ecuConfigId,
        ft.action_Type configTypeActionType,
        ft.external_id configTypeExternalId,
        fp.id propertyId, fp.config_type_id configTypeId,
        fp.property_name propertyName, fp.display_name displayName,
        fp.property_type propertyType, fp.property_options propertyOptionsStr,
        fp.description,fp.external_id configPropertyExternalId
        from t_ecu_config_type ft 
        left join t_ecu_config_property fp on ft.id = fp.config_type_id and ft.is_enable = fp.is_enable
        where ft.ecu_config_id = #{ecuConfigId}
        and ft.is_enable = 1
    </select>

可以看到,改造后的sql在第一层resultMap里的<collection>标签里加入了select属性引入子查询语句,column把第一段sql的column属性当参数传入子查询语句,这样出来的json结构和一开始的sql是一致的,但是mybatis分页插件会把它当作7条数据,而不是10条数据,就不会有分页数量信息和实际查询信息对不上的情况发生。

上一篇下一篇

猜你喜欢

热点阅读