仿照Mybatis-mate的字典功能的使用方式,进行代码实现

孟选
2023-12-01


前言

一、Mybtis-mate的引用官方jar包如何使用

第一步:先创建类,标志上相应注解。

@Data
public class User {
    private Long id;
    private String username;

    /**
     * type 绑定的是哪一个字典
     * target 给这个类里面的那个属性赋值
     */
    @FieldBind(type = BindType.USER_SEX, target = "sex")
    private String sex;

}

第二步:接口实现

@Component
public class DataBind implements IDataBindQA {

    @Resource
    ApplicationContext applicationContext;


    /**
     * 设置元数据对象<br>
     * 根据源对象映射绑定指定属性(自行处理缓存逻辑)
     *
     * @param fieldBind  数据绑定注解
     * @param fieldValue 属性值
     * @param metaObject 元数据对象 {@link MetaObject}
     * @return
     */
    @Override
    public void setMetaObject(DictAnno fieldBind, Object fieldValue, MetaObject metaObject) {
        //调用字典的service层
        ISysDictItemService dictService = applicationContext.getBean(ISysDictItemService.class);
        List<SysDictItem> sysDictItems = dictService.selectDictDataByType(fieldBind.type());
        //找到相应的数据
        Map<String, String> dictMap = sysDictItems.stream().collect(Collectors.toMap(dict -> dict.getDictValue(), dict -> dict.getDictLabel()));
        // 赋值
        metaObject.setValue(fieldBind.target(), dictMap.get(String.valueOf(fieldValue)));

    }
}

二、仿照官方Mybatis-mate的使用方法,代码实现

1.自定义一个注解

注解:

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface DictZP {
    String sharding() default "";

    String type();

    String target();
}

使用:

public class User {
    private Long id;

    private String username;

    /**
     * type 绑定的是哪一个字典
     * target 给这个类里面的那个属性赋值
     */
    @DictZP(type = BindType.USER_SEX, target = "sex")
    private String sex;

}

2.Mybatis的Interceptor 扩展

代码如下:

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.sdecloud.mybatismate.a.annotation.DictAnno;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.*;
@Slf4j
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
@Component
public class MyExecutor implements Interceptor {

    @Autowired
    private IDataBindZP iDataBindZP;//源码中是IDataBind,我则是定义为IDataBindZP 
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();

    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();

    private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();

    @Override
    @SuppressWarnings("unchecked")
    public Object intercept(Invocation invocation) throws Throwable {
    	//returnValue :这个returnValue就是已经查询出来的数据
        Object returnValue = invocation.proceed();
        // 使用反射对结果进行处理
        if (returnValue instanceof ArrayList<?>) {
            List<?> list = (ArrayList<?>) returnValue;
            if (CollUtil.isNotEmpty(list)) {
                Class<?> clazz = list.get(0).getClass();
                //获取所有的属性
                Field[] declaredFields = clazz.getDeclaredFields();
                list.forEach(obj -> {
                    MetaObject metaObject = MetaObject.forObject(obj, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, REFLECTOR_FACTORY);                    
                    Arrays.stream(declaredFields).forEach(field -> {
                    //判断属性之上是否有自己定义的注解
                        DictZP annotation = field.getAnnotation(DictZP.class);
                        if (ObjectUtil.isNotEmpty(annotation)) {
                        	//如果有,则进行转换
                            Object filedValue = metaObject.getValue(field.getName());
                            iDataBindZP.setMetaObject(annotation, filedValue, metaObject);
                        }
                    });
                });
            }
        }
        return returnValue;
    }


    @Override
    public Object plugin(Object target) {
        return  Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
    
}

3.接口定义

public interface IDataBindZP {
    void setMetaObject(DictZP var1, Object var2, MetaObject var3);
}

 类似资料: