• MyBatis Plus实现动态字段排序


    利用周末时间,对自己的项目进行了升级,原来使用的是tkmybatis,改为mybatis-plus。但是返回数据的格式变了,导致前端的客户端排序失效了,于是决定在服务端实现排序。

     

    目录

    前端代码

    role_list.html

    role_list.js

    后端代码

    controller层

    service层

    mapper层

    RoleAccount.java

    RoleAccountPager.java

    Pager.java

    Sorter.java


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

    前端代码

    role_list.html

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8" />
    5. <title>角色列表title>
    6. <link rel="stylesheet" href="/css/themes/icon.css"/>
    7. <link rel="stylesheet" href="/css/themes/default/easyui.css" />
    8. head>
    9. <body>
    10. <table id="role_list">table>
    11. <script src="/js/public/public.js">script>
    12. <script src="/js/public/jquery.min.js">script>
    13. <script src="/js/public/jquery.easyui.min.js">script>
    14. <script src="/js/public/easyui-lang-zh_CN.js">script>
    15. <script src="/js/role_account/role_list.js">script>
    16. body>
    17. html>

     

    role_list.js

    在需要开启排序功能的字段后面添加sortable:true的选项

    1. let pageList = [10, 20, 50, 100];
    2. $(document).ready(function() {
    3. // 角色数据表格
    4. $("#role_list").datagrid({
    5. url: '/role_account/selectByPage',
    6. striped: true,
    7. multiSort: true,
    8. fitColumns: true,
    9. remoteSort: true,
    10. singleSelect: true,
    11. height: table_height,
    12. pagination: true,
    13. pageList: pageList,
    14. pageSize: pageList[0],
    15. loadFilter: function(result){
    16. if (result.code === 200){
    17. return result.data;
    18. } else {
    19. return null;
    20. }
    21. },
    22. toolbar: [{
    23. iconCls: 'icon-add',
    24. text: '添加',
    25. handler: function() {
    26. handleAdd();
    27. }
    28. }, '-', {
    29. iconCls: 'icon-edit',
    30. text: '修改',
    31. handler: function() {
    32. handleUpdate();
    33. }
    34. }, '-', {
    35. iconCls: 'icon-set',
    36. text: '加点',
    37. handler: function() {
    38. handleJiadian();
    39. }
    40. }, '-', {
    41. iconCls: 'icon-shield',
    42. text: '属性',
    43. handler: function() {
    44. handleAttribute();
    45. }
    46. }, '-', {
    47. iconCls: 'icon-search',
    48. text: '查看',
    49. handler: function() {
    50. handleView();
    51. }
    52. }, '-', {
    53. iconCls: 'icon-tip',
    54. text: '关于',
    55. handler: function() {
    56. handleTip();
    57. }
    58. }],
    59. columns: [[
    60. {field: 'id', title: '角色ID', align: "center", sortable: true, width:100},
    61. {field: 'name', title: '角色名', align: "center", width: 120},
    62. {field: 'modelingId', title: '角色造型', align: "center", width: 80
    63. , formatter: function(value, rowData, rowIndex) {
    64. get("/role_modeling/selectById", {
    65. id: value
    66. }, function(result) {
    67. $("#modeling_" + rowIndex).attr("src", result.image)
    68. .attr("title", result.name);
    69. }, error);
    70. return "";
    71. }
    72. },
    73. {field: 'grade', title: '等级', align: "center", sortable: true, width: 80
    74. , formatter: function(value) {
    75. let group; // 组别
    76. if(value >= 0 && value <= 69) { // [0, 69]精锐组
    77. group = "精锐组";
    78. } else if(value >= 70 && value <= 89) { // [70, 89]勇武组
    79. group = "勇武组";
    80. } else if(value >= 90) { // [90, 115]神威组
    81. group = "神威组";
    82. } else { // [-∞, 0) ∪ (115, +∞)
    83. group = "等级不合法";
    84. }
    85. return "" + value+ "级";
    86. }
    87. },
    88. {field: 'score', title: '人物评分', align: "center", sortable: true, width: 80},
    89. {field: 'schoolId', title: '门派', align: "center", width: 80
    90. , formatter: function(value, rowData, rowIndex) {
    91. get("/school/selectById", {
    92. id: value
    93. }, function(result) {
    94. $("#school_" + rowIndex).attr("src", result.image)
    95. .attr("title", result.name).width(size);
    96. }, error);
    97. return "";
    98. }
    99. },
    100. {field: 'jinbi', title: '金币', align: "center", sortable: true, width: 80},
    101. {field: 'accountId', title: '账号', align: "center", width: 200
    102. , formatter: function(value, rowData, rowIndex) {
    103. get("/account/selectAccountById", {
    104. id: value
    105. }, function(response) {
    106. $("#account_" + rowIndex).html(response.data);
    107. }, error);
    108. return "
      "
      ;
    109. }
    110. },
    111. {field: "lastUpdateTime", title: "最后一次修改时间", align: "center", sortable: true, width: 125},
    112. {field: 'right', title: '操作', align: "center"
    113. , formatter: function(value, rowData, rowIndex) {
    114. return '
    115. }
    116. }
    117. ]]
    118. });
    119. });

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

    后端代码

    controller层

    RoleAccountController.java

    1. @RestController
    2. @RequestMapping(path = "/role_account", produces="application/json; charset=utf-8")
    3. public class RoleAccountController {
    4. private final IRoleAccountService service;
    5. @Autowired
    6. public RoleAccountController(IRoleAccountService service) {
    7. this.service = service;
    8. }
    9. @ApiOperation("分页查询角色列表")
    10. @RequestMapping(value = "/selectByPage", method = RequestMethod.POST)
    11. public JsonResult> selectByPage(RoleAccountPager pager) {
    12. Page page = service.selectByPage(pager);
    13. return JsonResult.restPage(page);
    14. }
    15. }

    service层

    RoleAccountServiceImpl.java

    1. @Service
    2. public class RoleAccountServiceImpl implements RoleAccountService {
    3. @Override
    4. public Page selectByPage(RoleAccountPager pager) {
    5. Page page = new Page<>(pager.getPage(), pager.getRows());
    6. QueryWrapper wrapper = new QueryWrapper<>();
    7. wrapper.eq(
    8. !StringUtils.isEmpty(pager.getId()),
    9. "id", pager.getId());
    10. wrapper.like(
    11. !StringUtils.isEmpty(pager.getName()),
    12. "name", pager.getName()
    13. );
    14. wrapper.eq(
    15. pager.getSchoolId() != null,
    16. "school_id", pager.getSchoolId()
    17. );
    18. wrapper.eq(
    19. pager.getModelingId() != null,
    20. "modeling_id", pager.getModelingId()
    21. );
    22. wrapper.eq(
    23. !StringUtils.isEmpty(pager.getAccountId()),
    24. "account_id", pager.getAccountId()
    25. );
    26. // 得到order by语句
    27. String statement = Pager.getOrderByStatement(pager);
    28. wrapper.last(statement);
    29. return mapper.selectPage(page, wrapper);
    30. }
    31. }

    mapper层

    RoleAccountMapper.java

    @Repository
    public interface RoleAccountMapper extends BaseMapper {
            
    }
    

    RoleAccount.java

    1. @Data
    2. public class RoleAccount {
    3. @TableId("id")
    4. private String id;
    5. /**
    6. * 角色名
    7. */
    8. private String name;
    9. /**
    10. * 等级
    11. */
    12. private Integer grade;
    13. /**
    14. * 人物评分
    15. */
    16. private Integer score;
    17. /**
    18. * 金币
    19. */
    20. private Integer jinbi;
    21. /**
    22. * 账号id
    23. */
    24. private String accountId;
    25. /**
    26. * 门派id
    27. */
    28. private Integer schoolId;
    29. /**
    30. * 服务器id
    31. */
    32. private Integer serverId;
    33. /**
    34. * 角色造型id
    35. */
    36. private Integer modelingId;
    37. /**
    38. * 账号创建时间
    39. */
    40. @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    41. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    42. private LocalDateTime birthday;
    43. /**
    44. * 最后一次修改时间
    45. */
    46. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    47. private LocalDateTime lastUpdateTime;
    48. }

     

    RoleAccountPager.java

    接收前端传递的查询参数

    1. @Data
    2. @EqualsAndHashCode(callSuper = true)
    3. public class RoleAccountPager extends Pager {
    4. /**
    5. * 角色id
    6. */
    7. private String id;
    8. /**
    9. * 角色名
    10. */
    11. private String name;
    12. /**
    13. * 等级
    14. */
    15. private Integer grade;
    16. /**
    17. * 账号id
    18. */
    19. private String accountId;
    20. /**
    21. * 门派id
    22. */
    23. private Integer schoolId;
    24. /**
    25. * 角色造型id
    26. */
    27. private Integer modelingId;
    28. }

     

    Pager.java

    1. /**
    2. * 基础分页对象,包含页数和每页的记录数
    3. */
    4. @Data
    5. @EqualsAndHashCode(callSuper = true)
    6. public class Pager extends Sorter {
    7. /**
    8. * 页数
    9. */
    10. private Integer page = 1;
    11. /**
    12. * 每页记录数
    13. */
    14. private Integer rows = 10;
    15. }

     

    Sorter.java

    以上是easyui官网的相关截图,当多字段排序时,传递给后台的参数中通过逗号拼接。

    【例如】:通过评分score升序和等级grade降序排序时,后台接收到的参数为:

    {

            "sort": "score,grade"

            "order": "asc,desc"

    }

     

    于是基于此规则,在Sorter.java中提供一个处理排序字段的方法

    1. /**
    2. * 基础排序对象,包含排序字段和排序方式
    3. */
    4. @Data
    5. public class Sorter {
    6. /**
    7. * 排序字段
    8. */
    9. private String sort;
    10. /**
    11. * 排序方式:asc/desc
    12. */
    13. private String order;
    14. /**
    15. * 根据查询条件拼接得到order by语句
    16. * @param sorter 分页查询条件
    17. * @return String
    18. */
    19. public static String getStatement(Sorter sorter) {
    20. String sort;
    21. String[] sortArray = {};
    22. String[] orderArray = {};
    23. String order = sorter.getOrder();
    24. String sortColumn = sorter.getSort();
    25. StringBuilder statement = new StringBuilder();
    26. // 多字段排序
    27. if (StringUtils.isNotEmpty(sortColumn)) {
    28. // 驼峰命名转为下划线
    29. sort = StringUtils.toLowerCase(sortColumn);
    30. if (sort.contains(",")) {
    31. sortArray = sort.split(",");
    32. }
    33. } else {
    34. return "";
    35. }
    36. if (StringUtils.isNotEmpty(order)) {
    37. if (order.contains(",")) {
    38. orderArray = order.split(",");
    39. }
    40. } else {
    41. return "";
    42. }
    43. if (sortArray.length > 0 && orderArray.length > 0) {
    44. int length = sortArray.length;
    45. for (int i = 0; i < length; i++) {
    46. statement.append(sortArray[i]);
    47. statement.append(" ");
    48. statement.append(orderArray[i]);
    49. if (i < length - 1 ) {
    50. statement.append(", ");
    51. }
    52. }
    53. } else {
    54. // " #{sort} #{order}“
    55. statement.append(sort);
    56. statement.append(" ");
    57. statement.append(order);
    58. }
    59. return statement.toString();
    60. }
    61. /**
    62. * 根据查询条件拼接得到order by语句
    63. * @param sorter 分页查询条件
    64. * @return String
    65. */
    66. public static String getOrderByStatement(Sorter sorter) {
    67. String statement = getStatement(sorter);
    68. if (StringUtils.isNotEmpty(statement)) {
    69. return " order by " + statement;
    70. } else {
    71. return statement;
    72. }
    73. }
    74. }

    因为排序的字段名是驼峰命名,需要转为小写字母+下划线命名,转换的方法抽象到了StringUtils工具类中,代码如下。

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

     

    通过继承关系,我们控制器接口的参数类型继承自Pager即自动获得分页和排序功能,只需要在构造条件查询器QueryWrapper时增加以下两行代码即可在后端开启多字段排序功能:

    1. String statement = Pager.getOrderByStatement(pager);
    2. wrapper.last(statement);

    好了,文章就分享到这里了,看完不要忘了点赞+收藏哦~

  • 相关阅读:
    Spring--IOC&&基于XML管理bean
    jdk11新特性——JShell交互性工具
    多边形内部水平方向近似最大矩形python实现
    代码随想录补打卡 121买卖股票的最佳时机 122 买卖股票的最佳时机 二123买卖股票的最佳时机 三
    CORS跨域资源共享+CORS的一系列响应头
    微服务项目:尚融宝(50)(核心业务流程:标的管理(2))
    9-2-Dataset创建-import调用
    【图像笔记】深度图像和深度相机
    “软件定义汽车”下的软件虚拟化技术
    基于JAVA高校学生资助管理信息系统计算机毕业设计源码+数据库+lw文档+系统+部署
  • 原文地址:https://blog.csdn.net/heyl163_/article/details/127608627