Java拖拽排序实现
Java推拽排序
说明
一般系统中有树形结构的地方都支持拖拽排序,包括同层级拖拽排序,跨层级拖拽排序,本文只针对同层级拖拽排序进行说明,跨层级拖拽后期更新。
影响元素位置的因素有三个,分别是新增、更新、删除,其中新增、删除不属于推拽类型,此次单独提出,便于统一理解。
示例表说明与字段说明:
equipment为设备表,order_num为排序字段
注意:所有排序操作都需要进行加锁,防止并发操作下数据排序错乱问题,示例代码如下:
private Lock lock = new ReentrantLock();
lock.lock();
try {
if (model.getOrderNum() == -1) {
// 排末位
// 相关操作
} else {
// 排首位 or 排中间
// 相关操作
}
} catch (Exception e) {
throw e;
} finally {
lock.unlock();
}
新增
一般我们在一个层级下新增数据时,数据默认都会插入到尾部,因此我们插入数据时需要找到最大的排序序号,然后将最大值+1即可将新元素插入到末尾,示例代码如下:
lock.lock();
try {
// 排末位
int maxSort = equipmentComplexMapper.selectMaxSortBySmallType(model.getSmallType());
equipmentMapper.insertSelective(model.withOrderNum(++maxSort));
} catch (Exception e) {
throw e;
} finally {
lock.unlock();
}
<select id="selectMaxSortBySmallType" resultType="byte">
select IFNULL(max(order_num), 0) from equipment where small_type = #{smallType} and status = 1
</select>
更新
拖拽更新分为四种情况,分别是:排末位、不变、前移、后移
排末位
排末位时,前端传递设备排序号为-1,找到最大的排序号,将更新的元素编号设置为最大编号,更新其他数据的排序编号。
不变
元素位置不变,不修改元素位置
前移
通过获取元素移动之前的排序编号与排序后的编号来确定需要变更编号的范围,将此范围下的编号统一更新。
后移
通过获取元素移动之前的排序编号与排序后的编号来确定需要变更编号的范围,将此范围下的编号统一更新。
参考实现如下:
- Service层

- Mapper层
获取排序最大的编号

前移时更新编号

后移时更新编号

删除
删除时,由于位置不固定,因此可以通过后台重置顺序的方式进行重排序,实现如下:
<update id="reinitializeSort">
<foreach collection="smallTypeList" item="smallType" index="i">
create temporary table temp_table_#{i}
select (@i:=@i+1) as sort, s.* from (select @i:=0) as it,
(select id, order_num from equipment where status = 1 and small_type = #{smallType} order by order_num) s;
update equipment e set e.order_num = (select t.sort from temp_table_#{i} t where e.id = t.id) where status = 1 and small_type = #{smallType};
drop table temp_table_#{i};
</foreach>
</update>