问题描述:
我们有个列表,分页只有三页,接口返回条数也只有53条
代码跟到最后,发现列表有联合查询,并且是一对多关系,左连接,查出来对象中的某个属性是list。
代码如下:
Page<BusinessContentInfoVO> page = new Page<>(param.getPageInfo().getPageNum(), param.getPageInfo().getPageSize());
param.setAppIds(appIds);
page = contentInfoMapper.page(page, param);
public interface BusinessContentInfoMapper extends BaseMapper<BusinessContentInfo> {
Page<BusinessContentInfoVO> page(Page<BusinessContentInfoVO> ipage, @Param("params") ContentInfoQO param);
List<BusinessContentInfoVO> getallContentByUsableState();
}
BusinessContentInfoMapper.xml (部分省略)如下
<resultMap id="BaseResultVOMap"
type="com.csp.microx.content.model.params.content.BusinessContentInfoVO">
<id column="content_id" property="contentId" />
<result column="content_title" property="contentTitle" />
...
<collection property="mediaStatus" ofType="com.csp.microx.content.model.params.content.BusinessContentInfoMediaStatusVO">
<result column="channel_name" property="channelName"/>
<result column="audit_status" property="auditStatus"/>
<result column="app_channel_id" property="appChannelId"/>
</collection>
</resultMap>
<select id="page" parameterType="com.csp.microx.content.model.params.content.ContentInfoQO"
resultMap="BaseResultVOMap">
SELECT
c.*,
channel.channel_name,channel.audit_status,channel.app_channel_id,t.puzzle_flag
FROM
business_content_info c
LEFT JOIN business_app a ON c.app_id = a.id
LEFT JOIN business_content_channel channel ON c.content_id = channel.content_id
LEFT JOIN business_template_info t ON c.template_code = t.template_code
<where>
<if test="params.contentTitle !=null and params.contentTitle !=''">
AND c.content_title like concat('%', #{params.contentTitle}, '%')
</if>
<if test="params.contentState !=null and params.contentState !=''">
AND c.content_state = #{params.contentState}
</if>
<if test="params.businessBelong !=null and params.businessBelong !=''">
AND c.business_belong = #{params.businessBelong}
</if>
<if test="params.beginTime !=null ">
AND c.create_time >= #{params.beginTime}
</if>
<if test="params.endTime !=null ">
AND c.create_time <= #{params.endTime}
</if>
</where>
order by c.create_time desc
</select>
如果没有分页,这种联合查询是没有问题的,business_content_info,主表确实只有53条数据,也没有问题,问题在于,查询第三页的时候,limit计算错误。
查询到的数据其实是连表查询的107条的第三页数据,所以导致接口查询不到全量数据。
解决方案
其实解决方法有好几种,最简单的一种,只需要修改BusinessContentInfoMapper.xml ,修改如下:
<resultMap id="BaseResultVOMap"
type="com.csp.microx.content.model.params.content.BusinessContentInfoVO">
<id column="content_id" property="contentId" />
<result column="content_title" property="contentTitle" />
...
<collection property="mediaStatus" ofType="com.csp.microx.content.model.params.content.BusinessContentInfoMediaStatusVO"
select="queryMediaList" column="content_id">
</collection>
</resultMap>
<select id="queryMediaList" resultType="com.csp.microx.content.model.params.content.BusinessContentInfoMediaStatusVO">
select channel.channel_name,channel.audit_status,channel.app_channel_id,channel.content_id
from business_content_channel channel
where channel.content_id = #{id}
</select>
<select id="page" parameterType="com.csp.microx.content.model.params.content.ContentInfoQO"
resultMap="BaseResultVOMap">
SELECT
c.content_id, c.content_title, c.content_type, c.business_belong, c.body_text,
c.create_time, c.creater, c.modify_time,
c.content_state, c.audit_opinion, c.app_id, a.app_name,
c.auditor, c.last_auditor,c.thumbnail,
c.content_source, c.create_source,c.chatbotH5_url,t.puzzle_flag
FROM
business_content_info c
LEFT JOIN business_app a ON c.app_id = a.id
LEFT JOIN business_template_info t ON c.template_code = t.template_code
<where>
<if test="params.contentTitle !=null and params.contentTitle !=''">
AND c.content_title like concat('%', #{params.contentTitle}, '%')
</if>
<if test="params.contentState !=null and params.contentState !=''">
AND c.content_state = #{params.contentState}
</if>
<if test="params.businessBelong !=null and params.businessBelong !=''">
AND c.business_belong = #{params.businessBelong}
</if>
<if test="params.beginTime !=null ">
AND c.create_time >= #{params.beginTime}
</if>
<if test="params.endTime !=null ">
AND c.create_time <= #{params.endTime}
</if>
</where>
order by c.create_time desc
</select>
因为项目中有成员有不良的修改方式,也能达到目标,将联查去掉,然后循环列表,再去查其他的子表。
这里面有个非常大的问题,在循环里面执行查询sql。影响数据库性能,影响接口响应速度。
但是非常不推荐,也不建议。