需求说明
最近有个需求:用户点击上下移动可以实现对数据自定义排序,每次移动一个位置。具体如下图所示:
实现思路
数据库表中添加一个order字段,默认设置为和主键一样的值,数据按照order降序排列
由于MySQL表只能有一个自增的键 (已设置为主键自增),所以这里的实现是每次插入数据后获取主键id的值,然后更新order字段的值(设置为id字段的值)。
上移操作
取出上一条记录的排序号,将当前记录与上一条记录的排序号调换位置
下移操作
取出下一条记录的排序号,将当前记录与下一条记录的排序号调换位置
相关代码
公告分类表的脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 CREATE TABLE `t_notice_type` ( `id` int (11 ) NOT NULL AUTO_INCREMENT COMMENT '公告分类 id' , `name` varchar (255 ) DEFAULT NULL COMMENT '分类名称' , `icon` varchar (255 ) DEFAULT NULL COMMENT '公告图标' , `status` int (1 ) DEFAULT NULL COMMENT '状态 0 开启 1 关闭' , `sort` int (3 ) NOT NULL DEFAULT '-1' COMMENT '排序' , `create_time` datetime DEFAULT NULL COMMENT '创建时间' , `update_time` datetime DEFAULT NULL COMMENT '修改时间' , `create_user` int (11 ) DEFAULT NULL COMMENT '创建者' , `last_update_user` int (11 ) DEFAULT NULL COMMENT '最后修改人' , PRIMARY KEY (`id`) USING BTREE ) ENGINE= InnoDB AUTO_INCREMENT= 12 DEFAULT CHARSET= utf8 ROW_FORMAT= DYNAMIC
AdjustOrderReq实体,用于接收前端请求入参,代码如下:
1 2 3 4 5 6 7 8 9 @Data public class AdjustOrderReq { @ApiModelProperty(value="公告分类id") private Integer id; @ApiModelProperty(value="排序方式") private Integer operaType; }
Controller请求方法代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @PostMapping("/adjustorder") @ApiOperation("公告分类顺序调整") public ResponseMsg adjustOrder (@RequestBody AdjustOrderReq orderReq) { if (!ObjectUtil.checkIsNotNull(orderReq)){ return this .errorRsp(MessageCode.Param_NULL); } if (!orderReq.getOperaType().equals(1 ) && !orderReq.getOperaType().equals(2 )){ return this .errorRsp(MessageCode.Param_Error); } int a = noticeTypeService.adjustOrder(orderReq); if (a != 1 ){ return this .errorRsp(MessageCode.Update_Error,String.valueOf(a)); } return this .successRsp(a); }
服务实现方法代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Override public int adjustOrder (AdjustOrderReq orderReq) { NoticeType noticeType = noticeTypeMapper.selectByPrimaryKey(orderReq.getId()); if (noticeType == null ){ log.info("NoticeServiceImpl.adjustOrder未查询到公告分类!" ); return -2 ; } if (orderReq.getOperaType().equals(1 )){ Integer nextId = noticeTypeMapper.selectNextId(noticeType); NoticeType nextNotice = noticeTypeMapper.selectByPrimaryKey(nextId); noticeType.setId(nextId); noticeTypeMapper.updateSortById(noticeType); nextNotice.setId(orderReq.getId()); noticeTypeMapper.updateSortById(nextNotice); } if (orderReq.getOperaType().equals(2 )){ Integer previousId = noticeTypeMapper.selectPreviousId(noticeType); NoticeType previousNotice = noticeTypeMapper.selectByPrimaryKey(previousId); noticeType.setId(previousId); noticeTypeMapper.updateSortById(noticeType); previousNotice.setId(orderReq.getId()); noticeTypeMapper.updateSortById(previousNotice); } return 1 ; }
MyBatis的XML映射文件代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <update id ="updateSortById" parameterType ="com.aspirecn.rewardmanagement.entity.NoticeType" > update t_notice_type set sort = #{sort},update_time = now() where id = #{id,jdbcType=INTEGER} </update > <select id ="selectPreviousId" resultType ="java.lang.Integer" parameterType ="com.aspirecn.rewardmanagement.entity.NoticeType" > SELECT IFNULL( (SELECT id FROM t_notice_type WHERE sort < #{sort} ORDER BY sort DESC LIMIT 0,1),1 ) AS preTypeId </select > <select id ="selectNextId" resultType ="java.lang.Integer" parameterType ="com.aspirecn.rewardmanagement.entity.NoticeType" > SELECT IFNULL( (SELECT id FROM t_notice_type WHERE sort > #{sort} ORDER BY sort asc LIMIT 0,1),1 ) AS nextTypeId </select >
selectByPrimaryKey方法作用是根据主键查询,代码就不贴了。
若有更好的实现方案或者上续代码有任何问题,都欢迎交流!
参考链接