MyBatis Plus实现动态字段排序

news2024/7/6 19:13:45

利用周末时间,对已有的项目进行了升级,原来使用的是tkmybatis,改为mybatis plus。但是由于修改了返回数据的格式,前端页面字段排序失效了,需要刷新表格才会排序。页面效果如下

easyui的数据表格datagrid支持多字段排序,以及可以控制是否通过服务器排序,核心代码如下。

role_list.html文件:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>角色列表</title>
		<link rel="stylesheet" href="/css/themes/icon.css"/>
		<link rel="stylesheet" href="/css/themes/default/easyui.css" />
	</head>
	
	<body>       
        <table id="role_list"></table>

		<script src="/js/public/public.js"></script>
		<script src="/js/public/jquery.min.js"></script>
		<script src="/js/public/jquery.easyui.min.js"></script>
		<script src="/js/public/easyui-lang-zh_CN.js"></script>
		<script src="/js/role_account/role_list.js"></script>
	</body>
</html>

role_list.js文件:

$(document).ready(function() {
    // 角色数据表格
	$("#role_list").datagrid({
		url: '/role_account/selectByPage',
		method: 'post',
		striped: true,
		multiSort: true,
		fitColumns: true,
		remoteSort: true,
		singleSelect: true,
		height: table_height,
		pagination: true,
		pageList: pageList,
		pageSize: pageList[0],
		loadFilter: function(result){
			if (result.code === 200){
				return result.data;
			} else {
				return null;
			}
		},
		toolbar: [{
			iconCls: 'icon-add',
			text: '添加',
			handler: function() {
				handleAdd();
			}
		}, '-', {
			iconCls: 'icon-edit',
			text: '修改',
			handler: function() {
				handleUpdate();
			}
		}],
		columns: [[
			{field: 'id', title: '角色ID', align:"center", width:100, sortable: true},
			{field: 'name', title: '角色名', align:"center", width:120},
			{field: 'modelingId', title: '角色造型', align:"center", width: 80
				, formatter: function(value, rowData, rowIndex) {
					$.get("/role_modeling/selectNameAndImageById", {
						id: value
					}, function(result) {
						$("#modeling_" + rowIndex).attr("src", result.image)
							.attr("title", result.name).width(size);
					});
					
					return "<img id='modeling_" + rowIndex + "' />";
				}
			},
			{field: 'grade', title: '等级', align: "center", sortable: true, width: 40
				, formatter: function(value) {
					let group; // 组别
					
					if(value >= 0 && value <= 69) { // [0, 69]精锐组
						group = "精锐组";
					} else if(value >= 70 && value <= 89) { // [70, 89]勇武组
						group = "勇武组";
					} else if(value >= 90) { // [90, 115]神威组
						group = "神威组";
					} else { // [-∞, 0) ∪ (115, +∞)
						group = "等级不合法";
					}
					
					return "<span title='" + group + "'>" + value+ "级</span>";
				}
			},
			{field: 'score', title: '人物评分', align:"center", sortable: true, width: 50},
			{field: 'schoolId', title: '门派', align:"center", width: 80
				, formatter: function(value, rowData, rowIndex) {
					$.get("/school/selectNameAndIconById", {
						id: value
					}, function(result) {
						$("#school_" + rowIndex).attr("src", result.icon)
							.attr("title", result.name).width(size);
					});
					
					return "<img id='school_" + rowIndex + "' />";
				}
			},
			{field: 'jinbi', title: '金币', align:"center", sortable: true, width: 50},
			{field: 'accountId', title: '账号', align:"center", width:200
				, formatter: function(value, rowData, rowIndex) {
					$.get("/account/selectAccountById", {
						id: value
					}, function(response) {
						$("#account_" + rowIndex).html(response.data);
					});
					
					return "<div id='account_" + rowIndex + "'></div>";
				}
			},
			{field: "lastUpdateTime", title: "最后一次修改", align: "center", width:125, sortable: true},
			{field: 'right', title: '操作', align:"center"
				, formatter: function(value, rowData, rowIndex) {
					let link = '<a href="javascript:;" ' + 'onclick="handleDelete(' + rowData.id + ')">'
						+ '<img title="删除" src="/css/themes/icons/delete.png" /></a>';
					
					return link;
				}
			}
		]]
	});

});

其中multiSort设置为true表示允许多字段排序,remoteSort表示是否从服务器排序,设置为true,我们接下来在后台接口处理字段排序。

以上是easyui官网的截图,当多字段排序时,传递给后台的参数中通过逗号拼接。例如:通过评分score升序和等级grade降序排序时,后台接收到的参数为:

{

        "sort": "score,grade"

        "order": "asc,desc"

}

controller代码:

@RestController
@RequestMapping(path = "/role_account", produces="application/json; charset=utf-8")
public class RoleAccountController {
   /**
	 * 分页条件查询角色列表
	 * @param pagerDTO 角色分页查询条件
	 * @return JsonPage<RoleAccount>
	 */
	@RequestMapping(path = "/selectByPage", method = RequestMethod.POST)
	public JsonResult<PageResult<RoleAccount>> selectByPage(RoleAccountPagerDTO pagerDTO) {
		return service.selectByPage(pagerDTO);
	}
}

service代码:

@Slf4j
@Service
public class RoleAccountServiceImpl implements IRoleAccountService {
    @Override
	public JsonResult<PageResult<RoleAccount>> selectByPage(RoleAccountPagerDTO pagerDTO) {
		Page<RoleAccount> page = new Page<>(pagerDTO.getPage(), pagerDTO.getRows());
		QueryWrapper<RoleAccount> wrapper = new QueryWrapper<>();

		wrapper.eq(!StringUtils.isEmpty(pagerDTO.getId()), "id", pagerDTO.getId());
		wrapper.like(!StringUtils.isEmpty(pagerDTO.getName()), "name", pagerDTO.getName());
		wrapper.eq(pagerDTO.getSchoolId() != null, "school_id", pagerDTO.getSchoolId());
		wrapper.eq(pagerDTO.getModelingId() != null, "modeling_id", pagerDTO.getModelingId());
		wrapper.eq(!StringUtils.isEmpty(pagerDTO.getAccountId()), "account_id", pagerDTO.getAccountId());

		// 得到order by语句
		String statement = BasePage.getOrderByStatement(pagerDTO);
		log.info("得到的order by语句:{}", statement.isEmpty() ? "空" : statement);
		wrapper.last(statement);

		Page<RoleAccount> result = mapper.selectPage(page, wrapper);

		return JsonResult.restPage(result);
	}
}

mapper代码:

@Repository
public interface RoleAccountMapper extends BaseMapper<RoleAccount> {
        
}

RoleAccount.java代码:

@Data
public class RoleAccount {
	@TableId("id")
	private String id;

	/**
	 * 角色名
	 */
	private String name;

	/**
	 * 等级
	 */
	private Integer grade;

	/**
	 * 人物评分
	 */
	private Integer score;

	/**
	 * 金币
	 */
	private Integer jinbi;

	/**
	 * 账号id
	 */
	private String accountId;

	/**
	 * 门派id
	 */
	private Integer schoolId;

	/**
	 * 服务器id
	 */
	private Integer serverId;

	/**
	 * 角色造型id
	 */
	private Integer modelingId;

	/**
	 * 账号创建时间
	 */
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
	private LocalDateTime birthday;

	/**
	 * 最后一次修改时间
	 */
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
	private LocalDateTime lastUpdateTime;
}

RoleAccountPagerDTO.java:

@Data
@EqualsAndHashCode(callSuper = true)
public class RoleAccountPagerDTO extends BasePage {
	/**
	 * 角色id
	 */
	private String id;

	/**
	 * 角色名
	 */
	private String name;

	/**
	 * 等级
	 */
	private Integer grade;

	/**
	 * 账号id
	 */
	private String accountId;

	/**
	 * 门派id
	 */
	private Integer schoolId;

	/**
	 * 角色造型id
	 */
	private Integer modelingId;
}

BasePage.java代码:

@Data
public class BasePage {
    /**
     * 页数
     */
    private Integer page;

    /**
     * 每页记录数
     */
    private Integer rows;

    /**
     * 排序字段
     */
    private String sort;

    /**
     * 排序方式:asc/desc
     */
    private String order;

    /**
     * 根据查询条件拼接得到order by语句
     * @param basePage 分页查询条件
     * @return String
     */
    public static String getStatement(BasePage basePage) {
        String sort;
        String[] sortArray = {};
        String[] orderArray = {};
        String order = basePage.getOrder();
        String sortColumn = basePage.getSort();
        StringBuilder statement = new StringBuilder();

        // 多字段排序
        if (StringUtils.isNotEmpty(sortColumn)) {
            // 驼峰命名转为下划线
            sort = StringUtils.toLowerCase(sortColumn);

            if (sort.contains(",")) {
                sortArray = sort.split(",");
            }
        } else {
            return "";
        }
        if (StringUtils.isNotEmpty(order)) {
            if (order.contains(",")) {
                orderArray = order.split(",");
            }
        } else {
            return "";
        }

        if (sortArray.length > 0 && orderArray.length > 0) {
            int length = sortArray.length;

            for (int i = 0; i < length; i++) {
                statement.append(sortArray[i]);
                statement.append(" ");
                statement.append(orderArray[i]);

                if (i < length - 1 ) {
                    statement.append(", ");
                }
            }
        } else {
            // " #{sort} #{order}“
            statement.append(sort);
            statement.append(" ");
            statement.append(order);
        }

        return statement.toString();
    }

    /**
     * 根据查询条件拼接得到order by语句
     * @param basePage 分页查询条件
     * @return String
     */
    public static String getOrderByStatement(BasePage basePage) {
        String statement = getStatement(basePage);

        // 多字段排序
        if (StringUtils.isNotEmpty(statement)) {
            return " order by " + statement;
        } else {
            return statement;
        }
    }

}

因为排序的字段名是驼峰命名,需要转为小写字母+下划线命名,否则sql语句会报错,找不到对应字段。转换的方法抽象到了StringUtils工具类中,代码如下。

public class StringUtils {
    /**
     * 判断字符串是否为null或""
     * 符串为""或null返回true,否则返回false
     * @param str 要判断的字符串
     * @return boolean
     */
    public static boolean isEmpty(String str) {
        return str == null || str.isEmpty();
    }

    /**
     * 判断字符串是否为""或null
     * 符串为""或null返回false,否则返回true
     * @param str 要判断的字符串
     * @return boolean
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 判断字符串是否为null或""
     * 符串为""或null返回true,否则返回false
     * @param str 要判断的字符串
     * @return boolean
     */
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.isEmpty();
    }

    /**
     * 检查字符串是否包含空白字符
     * 如果不包含空格返回true,否则返回false
     * @param str 需要比较的字符串
     * @return boolean
     */
    public boolean check(String str) {
        // 去除空白字符后字符串的长度
        int realLength = str.replaceAll("\\s", "").length();
        int originalLength = str.length(); // 字符串原来的长度

        return realLength == originalLength;
    }

    /**
     * 根据当前时间生成UUID
     * @return String
     */
    public static String uuid() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        LocalDateTime localDate = LocalDateTime.now();

        return localDate.format(formatter);
    }

    /**
     * 通过文件名获取文件类型
     * @param fileName 文件名
     */
    public static String getFileType(String fileName) {
        // 得到文件名中最后一次出现"."的位置
        int index = fileName.lastIndexOf('.');

        return fileName.substring(index);
    }

    /**
     * 获取文件名
     * @param file MultipartFile对象
     * @return String 由当前时间生成的新文件名
     */
    public static String getFileName(MultipartFile file) {
        // 得到上传文件的原始文件名
        String filename = file.getOriginalFilename();

        // 判断文件名是否为空
        if (isNullOrEmpty(filename)) {
            throw new RuntimeException("获取文件名失败!");
        }

        // 返回uuid.文件类型,如:20220618131456.jpg
        return uuid() + getFileType(filename);
    }

    /**
     * 功能:驼峰命名转下划线命名
     * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
     * @param str 待转换的字符串
     * @return String
     */
    public static String toLowerCase(String str) {
        str = str.replaceAll("([a-z])([A-Z])", "$1_$2");

        return str.toLowerCase();
    }

    /**
     * 功能:下划线命名转驼峰命名
     * 将下划线替换为空格,将字符串根据空格分割成数组,再将每个单词首字母大写
     * @param str 待转换的字符串
     * @return String
     */
    private static String toUpperCase(String str) {
        StringBuilder under= new StringBuilder();
        str = str.toLowerCase().replace("_", " ");
        String[] array = str.split(" ");

        for (String s : array) {
            String letter = s.substring(0, 1).toUpperCase() + s.substring(1);

            under.append(letter);
        }

        return under.toString();
    }

}

好了,本章就分享那么多了,感谢您的阅读~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2539.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【仿牛客网笔记】Spring Boot实践,开发社区登录模块-账号设置,检查登录

首先访问账号设置的页面。 新建一个Controller,用过RequestMapping生成访问路径 上传头像 首先打开配置文件&#xff0c;配置一下将文件配置到哪里。 直接在Controller存了&#xff0c; 更新的时候掉Map&#xff0c;参数为id和路径。 注入日志对象后&#xff0c;通过Val…

SpringBoot项目启动执行任务的几种方式

经过整理后得到以下几种常用方式&#xff0c;供大家参考。 1. 使用过滤器 init() &#xff1a;该方法在tomcat容器启动初始化过滤器时被调用&#xff0c;它在 Filter 的整个生命周期只会被调用一次。可以在这个方法中补充想要执行的内容。 Component public class MyFilter …

CTF竞赛网络安全大赛(网鼎杯 )Web|sql注入java反序列化

CTF竞赛网络安全大赛题目考点 sql注入 java反序列化 网鼎杯解题思路 题目一打开是这样的界面 下载题目的附件,并用jd-gui.exe打开 核心代码如下 Test代码 `` package 部分class;import cn.abc.common.bean.ResponseCode; import cn.abc.common.bean.ResponseResult; impor…

持续交付中流水线构建完成后就大功告成了吗?别忘了质量保障

上期文章我结合自己的实践经验&#xff0c;介绍了持续交付中流水线模式的软件构建&#xff0c;以及在构建过程中的3个关键问题。我们可以看出&#xff0c;流水线的软件构建过程相对精简、独立&#xff0c;只做编译 和打包两个动作。 但需要明确的是&#xff0c;在持续交付过程…

网课查题接口使用方法

网课查题接口使用方法 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点…

Hadoop面试题汇总-20221031

Hadoop面试题汇总 HDFS部分 1、请描述HDFS的写流程。 答&#xff1a; 首先由客户端向 NameNode 发起文件上传请求&#xff0c;NameNode 检查文件要上传的目录&#xff0c;并鉴权。如果上传用户对此目录有权限&#xff0c;则允许客户端进行上传操作。客户端接收到允许指令后&…

本科毕业论文内容必须有国内外文献综述吗?

不知不觉间整个暑假变过去了&#xff0c;现在大部分的大学生都已经开学了。2023届毕业的学生现在也开始借鉴毕业论文的选题工作。但是无论是现在正在选题的大四的同学们还是还在上大一大&#xff0c;二大三的同学们都对毕业论文这4个字有着天生的恐惧感。因为对于大多数人来说&…

阿里为何禁止在对象中使用基本数据类型

大家好&#xff0c;我是一航&#xff01; 前两天&#xff0c;因为一个接口的参数问题&#xff0c;和一位前端工程师产生了一些分歧&#xff0c;需求很简单&#xff1a; 根据一个数值类型&#xff08;type 取值范围1&#xff0c;2&#xff0c;3&#xff09;来查询数据&#xff…

HTML+CSS+JavaScript七夕情人节表白网页【樱花雨3D相册】超好看

这是程序员表白系列中的100款网站表白之一&#xff0c;旨在让任何人都能使用并创建自己的表白网站给心爱的人看。 此波共有100个表白网站&#xff0c;可以任意修改和使用&#xff0c;很多人会希望向心爱的男孩女孩告白&#xff0c;生性腼腆的人即使那个TA站在眼前都不敢向前表白…

pandas 基本数据

目录 1. pandas 简介 2. pandas 基本数据结构 2.1 Series 类型 2.1.1 索引-数据的行标签 2.1.2 值 2.1.3 切片 2.1.4 索引赋值 2.2 DataFrame 类型 1. pandas 简介 一般导入的形式&#xff1a;import pandas as pd 2. pandas 基本数据结构 python 的数据结构&#xff1a…

python爬虫之Scrapy框架,基本介绍使用以及用框架下载图片案例

一、Scrapy框架简介 Scrapy是:由Python语言开发的一个快速、高层次的屏幕抓取和web抓取框架&#xff0c;用于抓取web站点并从页面中提取结构化的数据&#xff0c;只需要实现少量的代码&#xff0c;就能够快速的抓取。 Scrapy使用了Twisted异步网络框架来处理网络通信&#xf…

Servlet篇 —— 我的第一个Servlet程序

☕导航小助手☕ &#x1f35a;写在前面 &#x1f35c;一、Maven的介绍 &#x1f371;​二、第一个Servlet的创建 &#x1f354;&#x1f354;2.1 创建项目 &#x1f969;&#x1f969;​2.2 引入依赖 &#x1f9aa;&#x1f9aa;​2.3 创建目录 &#x1f363;&#x1f363;2.4…

没想到GoFrame的gcache天然支持缓存淘汰策略

gcache提供统一的缓存管理模块&#xff0c;提供了开发者可自定义灵活接入的缓存适配接口&#xff0c;并默认提供了高速内存缓存适配实现。 先说结论 这篇文章通过结合商业项目的使用场景&#xff0c;为大家介绍了gcache的基本使用、缓存控制以及淘汰策略。 使用gcache做缓存处…

3分钟,快速上手Postman接口测试

Postman是一个用于调试HTTP请求的工具&#xff0c;它提供了友好的界面帮助分析、构造HTTP请求&#xff0c;并分析响应数据。实际工作中&#xff0c;开发和测试基本上都有使用Postman来进行接口调试工作。有一些其他流程的工具&#xff0c;也是模仿的Postman的风格进行接口测试工…

推荐 4 个开源工具

Hi&#xff0c;艾瑞巴蒂&#xff0c;晚上好&#xff01;今天推荐 4 个登上 GitHub 热搜的开源项目&#xff0c;它们分别是&#xff1a;1. 炫酷的 UI 工具&#xff1a;glslViewer2. Textual3. ToolJet&#xff1a;开源的低代码开发框架4. Linux 命令大全搜索工具01炫酷的 UI 工…

程序人生:去了字节跳动,才知道年薪40W的测试有这么多?

今年大环境不好&#xff0c;内卷的厉害&#xff0c;薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了&#xff1a; 哪家互联网公司薪资最‘厉害’&#xff1f; 下面的评论多为字节跳动&#xff0c;还炸出了很多年薪40W的测试工程师 我只想问一句&#xff0c;现在的…

vue3项目的创建,vite+vue3+ts(3)- router

vue3 有三种写法&#xff1a; 1.compostion API &#xff1a; 还是按照vue2.0写法 2.组合式API: 3. 组合式API 语法糖&#xff08;setup), 语法简洁&#xff08;推荐使用这个&#xff09; 写法&#xff1a; 4. 在.eslintrc.cjs 或者 .eslintrc.js中配置代码&#xff0c;是这个…

聊聊计算机中的寄存器

文章目录前言数据寄存器(DR)地址寄存器(AR)程序状态寄存器(PSW)累加寄存器(AC)乘商寄存器(MQ)程序计数器(PC)指令寄存器(IR)MAR、MDR小结作者&#xff1a;小牛呼噜噜 | https://xiaoniuhululu.com 计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 前…

国内第一篇讲解减少卡顿的代码级详细文章

原文链接&#xff1a;原文链接 系统网站应用出现过卡顿&#xff0c;但却不知道如何优化。国内第一篇讲如何减少卡顿的代码级别详细文章&#xff0c;也是性能优化系列文章中的一篇&#xff0c;欢迎点赞、关注&#xff0c;也欢迎对其中的内容进行评论。 经常听人说&#xff0c;“…

配置CentOS为ssh免密码互相通信

文章目录配置CentOS为ssh免密码互相通信配置4台CentOS的集群配置4台CentOS为ssh免密码互相通信配置CentOS为ssh免密码互相通信 配置4台CentOS的集群 修改 /etc/sysconfig/network-scripts/ifcfg-ens33 文件&#xff0c;配置虚拟机 IP&#xff0c;以其中一个虚拟机为例&#x…