记录做碧桂园项目时后端Java踩的坑

2年前 (2022) 程序员胖胖胖虎阿
225 0 0

转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客

记录做碧桂园项目时后端Java踩的坑

  • 项目名字:碧桂园文策系统(房地产项目)
    • 第一个坑:SQL查询速度慢
      • 踩坑之处:
        • 原SQL如下:
        • 原mybatis的mapper:
      • 解决方案:
        • 修改后的SQL:
        • 修改过后的mybatis的mapper:
    • 第二个坑:mybatis中LIMIT之后的语法问题
      • LIMIT语法分析:
      • LIMIT案例分析
      • 踩坑之处:
        • 原LIMIT语句:mybatis中使用LIMIT #{pageSize} // 错误(不能用#)
      • 解决方案:
        • 修改后的LIMIT语句:把#{pageSize} 改 ${pageSize} //正确

项目名字:碧桂园文策系统(房地产项目)

第一个坑:SQL查询速度慢

踩坑之处:

测试数据库中有40w+的数据,没查询一次这个接口要七秒的时间,即便做了mybatis_plus自动分页,还是查询速度慢,前端页面大概响应6,7秒左右才出第一页20条数据。

原SQL如下:

SELECT 
u.id, 
u.account, 
u.is_configured AS configured, 
u.is_resign AS resign, 
u.real_name AS realName, 
u.dept_code AS deptCode, 
u.bip_user_type AS bipUserType, 
u.status, 
u.role_id AS roleId, 
u.type, 
u.create_time AS createTime, 
u.update_time AS updateTime, 
GROUP_CONCAT(CASE WHEN r.name != '' THEN r.name END) AS roleName 
FROM user u 
LEFT JOIN dept d
ON u.dept_code = d.dept_code 
LEFT JOIN role r ON FIND_IN_SET(r.id, u.role_id) 
WHERE 
u.is_configured = 0 
AND u.is_resign = 0 
AND u.type = 1 
AND u.is_deleted = 0 
GROUP BY u.id 
ORDER BY u.update_time DESC, 
u.id DESC

原mybatis的mapper:

   <select id="listUserConfigManage" resultType="com.bgy.entity.result.ListUserConfigManageResult">
        select
        u.id,
        u.account,
        u.is_configured AS configured,
        u.is_resign AS resign,
        u.real_name AS realName,
        u.dept_code AS deptCode,
        u.bip_user_type AS bipUserType,
        u.status,
        u.role_id AS roleId,
        u.type ,
        u.create_time AS createTime,
        u.update_time AS updateTime,
        GROUP_CONCAT(case when r.name!='' then r.name end) AS roleName
        from user u
        left join dept d
        on u.dept_code=d.dept_code
        left join role r
        on FIND_IN_SET(r.id,u.role_id)
        <where>
            <if test="vo.configured==0">
                and u.is_configured=0 and u.is_resign=0
            </if>
            <if test="vo.configured==1">
                and u.is_configured=1 and u.is_resign=0
            </if>
            <if test="vo.configured==2">
                and u.is_resign=1
            </if>
            <if test="vo.deptCode!=null">
                and u.dept_code=#{vo.deptCode}
            </if>
            <if test="vo.userName!=null">
                and (u.account=#{vo.userName} or u.real_name=#{vo.userName})
            </if>
            <if test="vo.type!=null">
                and u.type=#{vo.type}
            </if>
            and u.is_deleted=0
        </where>
        GROUP BY u.id
        order by u.update_time desc,u.id desc
    </select>

解决方案:

修改SQL为手动分页+先按条件查询后再进行分组最后排序(利用子查询的方法)。

优化了SQL后,查询第一页前20条数据只需要2秒时间就可查出结果了,由自动分页改成手动分页,需注意limit的参数问题:LIMIT

(

v

o

.

p

a

g

e

1

)

v

o

.

l

i

m

i

t

,

{(vo.page-1)*vo.limit},

(vo.page1)vo.limit,{vo.limit}(下面会继续记录分页踩的坑)

修改后的SQL:

 select 
 temp.*, 
 GROUP_CONCAT(case when r.name!='' then r.name end) AS roleName 
 from ( 
	select 
	u.id, 
	u.account,
	u.is_configured AS configured,
	u.is_resign AS resign,
	u.real_name AS realName, 
	u.dept_code AS deptCode,
	u.bip_user_type AS bipUserType, 
	u.status,
	u.role_id AS roleId, 
	u.type , 
	u.create_time AS createTime, 
	u.update_time AS updateTime 
	from user u 
	left join dept d 
	on u.dept_code=d.dept_code 
	WHERE u.type=1 and u.is_deleted=0  limit 0,20
	) temp 
left join role r 
on FIND_IN_SET(r.id,temp.roleId) 
GROUP BY temp.id 
order by temp.updateTime desc,temp.id desc

修改过后的mybatis的mapper:

<select id="list" resultType="com.bgy.entity.result.ListUserConfigManageResult">
        select
            temp.*,
            GROUP_CONCAT(case when r.name!='' then r.name end) AS roleName
        from (
                select
                u.id,
                u.account,
                u.is_configured AS configured,
                u.is_resign AS resign,
                u.real_name AS realName,
                u.dept_code AS deptCode,
                u.bip_user_type AS bipUserType,
                u.status,
                u.role_id AS roleId,
                u.type ,
                u.create_time AS createTime,
                u.update_time AS updateTime
                from user u
                left join dept d
                on u.dept_code=d.dept_code
                <where>
                    1 = 1
                        <if test="vo.configured==0">
                           and u.is_configured=0 and u.is_resign=0
                        </if>
                        <if test="vo.configured==1">
                            and u.is_configured=1 and u.is_resign=0
                        </if>
                        <if test="vo.configured==2">
                            and u.is_resign=1
                        </if>
                        <if test="vo.deptCode!=null">
                            and u.dept_code=#{vo.deptCode}
                        </if>
                        <if test="vo.userName!=null">
                            and u.account=#{vo.userName} or u.real_name=#{vo.userName}
                        </if>
                        <if test="vo.type!=null">
                            and u.type=#{vo.type}
                        </if>
                        and u.is_deleted=0
                    </where>
                        LIMIT ${(vo.page-1)*vo.limit},${vo.limit}
            ) temp
        left join role r
        on FIND_IN_SET(r.id,temp.roleId)
        GROUP BY temp.id
        order by temp.updateTime desc,temp.id desc
    </select>

    <select id="selectCount" resultType="java.lang.Integer">
        select
        count(*)
        from user u
        <where>
            1 = 1
            <if test="vo.configured==0">
               and u.is_configured=0 and u.is_resign=0
            </if>
            <if test="vo.configured==1">
                and u.is_configured=1 and u.is_resign=0
            </if>
            <if test="vo.configured==2">
                and u.is_resign=1
            </if>
            <if test="vo.deptCode!=null">
                and u.dept_code=#{vo.deptCode}
            </if>
            <if test="vo.userName!=null">
                and (u.account=#{vo.userName} or u.real_name=#{vo.userName})
            </if>
            <if test="vo.type!=null">
                and u.type=#{vo.type}
            </if>
            and u.is_deleted=0
        </where>
    </select>

第二个坑:mybatis中LIMIT之后的语法问题

LIMIT语法分析:

客户端通过传递page(页码),limit(每页显示的条数)两个参数去分页查询数据库表中的数据,我们知道MySql数据库提供了分页的函数LIMIT m,n。

LIMIT后面,可以跟两个参数

第一个参数,OFFSET,可选参数,表示偏移量,如果不指定默认值为0

如果,偏移量为0,则从查询结果的第一条记录开始,偏移量为1,则从查询结果中的第二条记录开始,以此类推

第二个参数,记录数,表示返回查询结果的条数

LIMIT案例分析

参考博客:https://blog.csdn.net/u013182595/article/details/109293991
例如:

     查询第1条到第10条的数据的sql是:select * from table limit 0,10;   ->对应我们的需求就是查询第一页的数据:select * from table limit (1-1)*10,10;

     查询第11条到第20条的数据的sql是:select * from table limit 10,10;  ->对应我们的需求就是查询第二页的数据:select * from table limit (2-1)*10,10;

    通过上面的分析,可以归纳得出符合需求的分页SQL伪代码,如下所示。总之,我们只需要告诉数据库要从第几行开始拿多少条数据就行了。

mysql分页:select * from 表 limit (page-1)*limit,limit;

oracle分页:select a.* (select 表.*,rowum rn from 表) a where rn>(page-1)limit and rn <=pagelimit;

踩坑之处:

原LIMIT语句:mybatis中使用LIMIT #{pageSize} // 错误(不能用#)

在上述SQL中由mybatis_plus自动分页改成了mybatis手动分页
最开始用的是: LIMIT  #{vo.page}-1*#{vo.limit},#{vo.limit};//错误的
无法计算

解决方案:

修改后的LIMIT语句:把#{pageSize} 改 ${pageSize} //正确

把SQL中的LIMIT改成这样: LIMIT ${(vo.page-1)*vo.limit},${vo.limit}

版权声明:程序员胖胖胖虎阿 发表于 2022年10月30日 上午8:24。
转载请注明:记录做碧桂园项目时后端Java踩的坑 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...