飞道的博客

关于mybatis plus 中的查询优化

293人阅读  评论(0)

传统的mybatis plus 查询写法

对于常规的mybatis单表查询,我们既可以采用LambdaQueryWrapper查询,也可以使用QueryWrapper查询。
LambdaQueryWrapper具有防误写、规范代码等好处,但是缺点是无法在复杂的多表查询中使用。
相比较来说,使用QueryWrapper编写查询更加灵活,可以适应更复杂的查询场景。
我们首先看一个QueryWrapper查询的例子


  
  1. public List<UserMo> list (UserForm userForm) {
  2. QueryWrapper<UserMo> queryWrapper = new QueryWrapper<>();
  3. queryWrapper.like(StringTool.isNotEmpty(userForm.getUserName(), "name", userForm.getUserName());
  4. queryWrapper.eq(StringTool.isNotEmpty(userForm.getMobile(), "mobile", userForm.getMobile());
  5. // 其它的查询条件...
  6. return userMapper.selectList(queryWrapper);
  7. }

对于上面的查询语句来说,可以很好的对前端传值进行处理,当userForm中有前端传值的话,就会往SQL语句中加一条where条件。
但是这样做的话会有一个相对来说比较复杂的点,那就是当UserForm中的字段过于多的时候,我们也许得写十几行的这种重复判断的语句。  

通过自定义注解来解决通用查询条件过多问题

通过观察mybatis plus 对于queryWrapper相关查询方法的列子,我们可以找出一类通用方法

可以看出来这几个方法都是传的同样的三个参数。
我想对于这些简单的通用的查询条件,也许可以有一个通用的方法来填充。
我首先设置了一个枚举类,将这些查询条件列出来,并在构造方法中,将对应的方法以反射的方式取到。 

 


  
  1. public enum QueryConditionEnum {
  2. EQ( "eq"),
  3. NE( "ne"),
  4. GT( "gt"),
  5. GE( "ge"),
  6. LT( "lt"),
  7. LE( "le"),
  8. LIKE( "like"),
  9. NOT_LIKE( "notLike"),
  10. LIKE_LEFT( "likeLeft"),
  11. LIKE_RIGHT( "likeRight");
  12. private String name;
  13. private Method method;
  14. QueryConditionEnum (String name) {
  15. this.name = name;
  16. try {
  17. Method method = AbstractWrapper. class.getDeclaredMethod(name, boolean. class, Object. class, Object. class);
  18. this.method = method;
  19. } catch (NoSuchMethodException e) {
  20. }
  21. }
  22. }

再者,我想通过注解的方式来规定需要以什么方法填充,默认为EQ,对此写了一个QueryCondition注解。  

 


  
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target({ElementType.FIELD})
  3. public @interface QueryCondition {
  4. /**
  5. * 默认查询方式
  6. *
  7. * @return
  8. */
  9. QueryConditionEnum value() default QueryConditionEnum .EQ;
  10. /**
  11. * 是否填充默认查询条件
  12. *
  13. * @return
  14. */
  15. boolean isCondition() default true;
  16. }

然后就可以这样构造UserForm  

 


  
  1. public class UserForm {
  2. private String name;
  3. @QueryCondition(QueryConditionEnum.LIKE)
  4. private String mobile;
  5. }

我们需要一个工具类填充查询条件,这里我们新增了一个参数 mo对象,这是因为我们的主查询对象是Mo对象,Mo对象存储了相关表格名称、表格字段名信息。  

 


  
  1. @TableName("user")
  2. public class UserMo {
  3. @TableField("name")
  4. private String name;
  5. @TableField("mobile")
  6. private String mobile;
  7. }

 


  
  1. public class QueryTool {
  2. /**
  3. * 填充默认查询
  4. * @param baseClazz mo对象class
  5. * @param queryWrapper 查询条件
  6. * @param form 请求对象
  7. */
  8. public static void paddingDefaultConditionQuery( Class baseClazz, QueryWrapper queryWrapper, Object form) {
  9. try {
  10. for (Field declaredField : form.getClass().getDeclaredFields()) {
  11. declaredField.setAccessible( true);
  12. Object fieldValue = declaredField.get(form);
  13. QueryCondition queryCondition = declaredField.getAnnotation(QueryCondition. class);
  14. if (fieldValue == null) {
  15. continue;
  16. }
  17. if (queryCondition == null) {
  18. queryWrapper.eq(StringTool.isNotEmpty(fieldValue.toString()),
  19. QueryTool.getTableName(baseClazz) + "." + QueryTool.getTableFieldName(baseClazz, declaredField),
  20. fieldValue.toString());
  21. continue;
  22. }
  23. if (queryCondition.isCondition() == false) {
  24. continue;
  25. }
  26. Method method = queryCondition.value().getMethod();
  27. method.invoke(queryWrapper, StringTool.isNotEmpty(fieldValue.toString()),
  28. QueryTool.getTableName(baseClazz) + "." + QueryTool.getTableFieldName(baseClazz, declaredField),
  29. fieldValue.toString());
  30. }
  31. } catch ( Exception e) {
  32. throw new RuntimeException( "填充默认的SQL条件出错", e);
  33. }
  34. }
  35. /**
  36. * 填充默认排序
  37. *
  38. * @param queryWrapper
  39. * @param pageForm
  40. */
  41. public static void paddingDefaultOrderQuery(QueryWrapper queryWrapper, PageForm pageForm) {
  42. queryWrapper.orderBy(pageForm != null && StringTool.isNotEmpty(pageForm.getColumnName()),
  43. pageForm.getIsAsc() == null ? false : pageForm.getIsAsc(), pageForm.getColumnName());
  44. }
  45. /**
  46. * 获取表名称
  47. *
  48. * @return
  49. */
  50. public static String getTableName( Class baseClazz) {
  51. TableName tableName = (TableName) baseClazz.getDeclaredAnnotation(TableName. class);
  52. if (tableName != null && StringTool.isNotEmpty(tableName.value())) {
  53. return tableName.value();
  54. }
  55. return StringTool.toUnderline(baseClazz.getClass().getName());
  56. }
  57. /**
  58. * 获取字段名
  59. *
  60. * @param field
  61. * @ return
  62. */
  63. public static String getTableFieldName( Class baseClazz, Field field) {
  64. Field baseField = null;
  65. try {
  66. baseField = baseClazz.getDeclaredField(field.getName());
  67. } catch (NoSuchFieldException e) {
  68. e.printStackTrace();
  69. }
  70. if (baseField == null) {
  71. baseField = field;
  72. }
  73. TableId tableId = baseField.getAnnotation(TableId. class);
  74. if (tableId != null && StringTool.isNotEmpty(tableId.value())) {
  75. return tableId.value();
  76. }
  77. TableField tableField = baseField.getAnnotation(TableField. class);
  78. if (tableField != null && StringTool.isNotEmpty(tableField.value())) {
  79. return tableField.value();
  80. }
  81. return StringTool.toUnderline(baseField.getName());
  82. }
  83. }

最后我们就可以使用工具类来填充了 。

 


  
  1. public List<UserMo> list (UserForm userForm) {
  2. QueryWrapper<UserMo> queryWrapper = new QueryWrapper<>();
  3. QueryTool.paddingDefaultConditionQuery(UserMo. class, queryWrapper, userForm);
  4. return userMapper.selectList(queryWrapper);
  5. }

 

可以看到这样大大减少了需要填充的字段。如果有特殊字段,也能通过注解方式,跳过特殊字段,再自行填充就好。

 

作者:李涛


转载:https://blog.csdn.net/m0_46573967/article/details/112857333
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场