通过注解和反射将实体类快速转为为Wrapper对象

通过注解和反射将实体类快速转为为Wrapper对象

一、思路

  1. 在实体类中需要参与判断的字段上添加注解@Wrapper,
  2. value()对应wrapper上的对应操作(eq,lt,gt等),
  3. column()的值为该字段对应数据库中的列名,默认是字段名。
  4. 通过反射获取实体类上的字段集合fields,
  5. 遍历fields,获取每个field的值和注解,
  6. 解析注解上的value()和column(),根据这两个值增加该字段对应的wrapper操作。

二、实现

  1. 构建一个基于 SpringBoot+MyBatis-Plus 的项目。

  2. 创建数据表student并填充测试数据
    创建数据表并填充测试数据

  3. 创建实体类Student,
    将name字段添加@Wrapper,不另外设置值,
    value()将默认为Comparison.EQ,
    column()为空,将使用字段名作为列名
    将age字段改为age1,自定义column()的值,设置字段对应相应的列名为column()的值

package com.hsh.MySQLUtil.model;

import com.baomidou.mybatisplus.annotation.TableField;
import com.hsh.MySQLUtil.annotation.Wrapper;
import com.hsh.MySQLUtil.enmu.Comparison;
import lombok.Data;

/**
 * @author hsh
 * @date 2023/7/26 22:07
 */
// 可以使用lombok的@Data注解自动生成其set/get方法
@Data 
public class Student {

    private Integer id;
    
    @Wrapper
    private String name;
    
    @Wrapper(value = Comparison.LT, column = "age")
    private Integer age1;
    
}
  1. 添加Student的配置文件 StudentMapper.xml dao层接口的StudentMapper.java,service的接口和实现类可以暂时不创建。可以通过MyBatisX插件批量生成这些文件
    链接: https://blog.csdn.net/SUMMERENT/article/details/129587241

  2. pom.xml中添加hutool依赖,hutool包里包装了通过反射获取类中的字段,获取字段中的值的方法。

<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>4.1.0</version>
</dependency>

  1. 新建比较类型的枚举类Comparison
package com.hsh.MySQLUtil.enmu;

/**
 * @author hsh
 * @date 2023/7/26 22:37
 */
public enum Comparison {
    EQ,
    LT,
    GT
}

  1. 新建注解@Wrapper
package com.hsh.MySQLUtil.annotation;

import com.hsh.MySQLUtil.enmu.Comparison;

import java.lang.annotation.*;

/**
 * @author hsh
 * @date 2023/7/26 22:38
 */
@Target(ElementType.FIELD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Wrapper {

    //默认使用eq,一个字段上只能使用一个Wrapper注解
    Comparison value() default Comparison.EQ;

    //设置该字段对应的列名
    String column() default "";

}

  1. 新建构建Wrapper的工具类QueryWrapperBuilder
package com.hsh.MySQLUtil.util;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hsh.MySQLUtil.annotation.Wrapper;
import com.hsh.MySQLUtil.enmu.Comparison;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;

/**
 * @author hsh
 * @date 2023/7/27 19:58
 */
public class QueryWrapperBuilder {
    public static <T> QueryWrapper<T> buildQueryWrapper(T t) {
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        if (t == null) {
            return wrapper;
        }
        //hutool包装的方法,获得一个类中所有字段列表,包括其父类中的字段和私有字段
        //相当于getDeclaredFields()和getFields()的结合体
        Field[] fields = ReflectUtil.getFields(t.getClass());
        List<Field> list = Arrays.asList(fields);
        if (list.isEmpty()) {
            return wrapper;
        }
        for (Field field : list) {
            //hutool包装的方法,与field.get(t)类似,但不需要try/catch
            Object value = ReflectUtil.getFieldValue(t, field.getName());
            //字段值为空时不参与条件查询
            if (value == null || "".equals(value)) {
                continue;
            }
            //允许访问私有字段
            field.setAccessible(true);
            //获取Wrapper注解
            Wrapper wrapperAnno = field.getAnnotation(Wrapper.class);
            if (wrapperAnno == null) {
                continue;
            }
            //设置该字段对应数据库的列名,默认字段名=列名
            String name = wrapperAnno.column().isEmpty()
                    ? field.getName()
                    : wrapperAnno.column();
            //根据注解的值添加对应的wrapper操作
            switch (wrapperAnno.value()) {
                case EQ:
                    wrapper.eq(name, value);
                    break;
                case LT:
                    wrapper.lt(name, value);
                    break;
                case GT:
                    wrapper.gt(name, value);
                    break;
            }
        }
        return wrapper;
    }
}

  1. 为了测试步骤简洁,直接在Controller生成Wrapper对象并调用
package com.hsh.MySQLUtil.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hsh.MySQLUtil.mapper.StudentMapper;
import com.hsh.MySQLUtil.model.Student;
import com.hsh.MySQLUtil.util.QueryWrapperBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author hsh
 * @date 2023/7/24 4:01
 */
@RestController
public class StudentController {
    @Resource
    private StudentMapper studentMapper;
    
    @GetMapping("/find")
    public List find() {
//        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("age",18);
        Student student = new Student();
        student.setAge1(19);
        student.setName("张三");
        QueryWrapper<Student> queryWrapper = QueryWrapperBuilder.buildQueryWrapper(student);
        List<Student> students = studentMapper.selectList(queryWrapper);
        System.out.println(students);
        return students;
    }
}

  1. 可以看到已经可以通过student对象生成对应的wrapper对象,并生成对应的sql语句。
    后端控制台显示
    前端浏览器显示
Logo

数据库是今天社会发展不可缺少的重要技术,它可以把大量的信息进行有序的存储和管理,为企业的数据处理提供了强大的保障。

更多推荐