文章目录

  • 需求说明
  • 实现思路
  • 相关代码


需求说明

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

java 实现上下移动 java上移下移_Code

实现思路

  • 数据库表中添加一个order字段,默认设置为和主键一样的值,数据按照order降序排列
    由于MySQL表只能有一个自增的键(已设置为主键自增),所以这里的实现是每次插入数据后获取主键id的值,然后更新order字段的值(设置为id字段的值)。
  • 上移操作
    取出上一条记录的排序号,将当前记录与上一条记录的排序号调换位置
  • 下移操作
    取出下一条记录的排序号,将当前记录与下一条记录的排序号调换位置

相关代码

公告分类表脚本如下:

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实体,用于接收前端请求入参,代码如下:

@Data
public class AdjustOrderReq {

    @ApiModelProperty(value="公告分类id")
    private Integer id;

    @ApiModelProperty(value="排序方式")
    private Integer operaType;//1上移 2下移
}

Controller请求方法代码如下:

@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);
    }

服务实现方法代码如下:

@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映射文件代码如下:

<!--根据主键更新排序号-->
  <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 < #{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 ">> #{sort}
    ORDER BY  sort asc LIMIT 0,1),1
    ) AS nextTypeId
  </select>

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