Java实现列表中上移、下移操作

需求说明

最近有个需求:用户点击上下移动可以实现对数据自定义排序,每次移动一个位置。具体如下图所示:
在这里插入图片描述

实现思路

  • 数据库表中添加一个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;//1上移 2下移
}

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) {
// 1、查询是否存在分类
NoticeType noticeType = noticeTypeMapper.selectByPrimaryKey(orderReq.getId());
if(noticeType == null){
log.info("NoticeServiceImpl.adjustOrder未查询到公告分类!");
return -2;
}
// 2、上移
if(orderReq.getOperaType().equals(1)){
//查询下一条记录Id和sort
Integer nextId = noticeTypeMapper.selectNextId(noticeType);
NoticeType nextNotice = noticeTypeMapper.selectByPrimaryKey(nextId);
//更新下一条记录的sort为当前值
noticeType.setId(nextId);
noticeTypeMapper.updateSortById(noticeType);
//更新当前记录的sort为下一条
nextNotice.setId(orderReq.getId());
noticeTypeMapper.updateSortById(nextNotice);
}
// 3、下移动
if(orderReq.getOperaType().equals(2)){
//查询上一条记录Id和sort
Integer previousId = noticeTypeMapper.selectPreviousId(noticeType);
NoticeType previousNotice = noticeTypeMapper.selectByPrimaryKey(previousId);
//更新上一条记录的sort为当前值
noticeType.setId(previousId);
noticeTypeMapper.updateSortById(noticeType);
//更新当前记录的sort为上一条
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>
<!--根据sort查询上一条记录主键-->
<select id="selectPreviousId" resultType="java.lang.Integer" parameterType="com.aspirecn.rewardmanagement.entity.NoticeType">
SELECT IFNULL(
(SELECT id FROM t_notice_type WHERE sort &lt; #{sort}
ORDER BY sort DESC LIMIT 0,1),1
) AS preTypeId
</select>
<!--根据sort查询下一条记录主键-->
<select id="selectNextId" resultType="java.lang.Integer" parameterType="com.aspirecn.rewardmanagement.entity.NoticeType">
SELECT IFNULL(
(SELECT id FROM t_notice_type WHERE sort &gt; #{sort}
ORDER BY sort asc LIMIT 0,1),1
) AS nextTypeId
</select>

selectByPrimaryKey方法作用是根据主键查询,代码就不贴了。
若有更好的实现方案或者上续代码有任何问题,都欢迎交流!
参考链接