其他分享
首页 > 其他分享> > Mybatis自动注册TypeHandler,自动扫描、自定义注解实现自定义TypeHandler

Mybatis自动注册TypeHandler,自动扫描、自定义注解实现自定义TypeHandler

作者:互联网

上一篇手动版https://blog.csdn.net/h785160953/article/details/103615458

自定义的TypeHandler


import com.dreawer.domain.BaseDomain;
import com.dreawer.persistence.config.DwDaoHandler;
import com.dreawer.persistence.config.DwMybatisConfig;
import com.dreawer.util.JsonUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 数据库字段string - Java对象互转handler
 *
 * @author Leo.Xi
 * @date 2019/12/18
 * @since 1.0
 **/
@MappedJdbcTypes({JdbcType.VARCHAR, JdbcType.CHAR, JdbcType.NCHAR, JdbcType.LONGVARCHAR})
public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {

    public static final String ID_TEMPLATE = "{\"id\":\"%s\"}";

    private Class<? extends T> clazz;// clazz
    private DwDaoHandler.Type type;// 序列化类型

    public JsonTypeHandler(Class<? extends T> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.clazz = clazz;
        this.type = DwMybatisConfig.getSingleType(clazz);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            ps.setString(i, JsonUtils.toNoNullJsonStr(parameter));
        } else {
            ps.setString(i, ((BaseDomain) parameter).getId());
        }
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            return JsonUtils.readValue(rs.getString(columnName), clazz);
        } else {
            return JsonUtils.readValue(String.format(ID_TEMPLATE, rs.getString(columnName)), clazz);
        }
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            return JsonUtils.readValue(rs.getString(columnIndex), clazz);
        } else {
            return JsonUtils.readValue(String.format(ID_TEMPLATE, rs.getString(columnIndex)), clazz);
        }
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            return JsonUtils.readValue(cs.getString(columnIndex), clazz);
        } else {
            return JsonUtils.readValue(String.format(ID_TEMPLATE, cs.getString(columnIndex)), clazz);
        }
    }

}

import com.dreawer.domain.BaseDomain;
import com.dreawer.persistence.config.DwDaoHandler;
import com.dreawer.persistence.config.DwMybatisConfig;
import com.dreawer.util.JsonUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据库字段string - Java对象互转handler
 *
 * @author Leo.Xi
 * @date 2019/12/18
 * @since 1.0
 **/
@MappedJdbcTypes({JdbcType.VARCHAR, JdbcType.CHAR, JdbcType.NCHAR, JdbcType.LONGVARCHAR})
public class JsonListTypeHandler<T extends Object> extends BaseTypeHandler<List<T>> {

    private Class<? extends T> clazz;// clazz
    private DwDaoHandler.Type type;// 序列化类型

    public JsonListTypeHandler(Class<? extends T> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.clazz = clazz;
        this.type = DwMybatisConfig.getCollectionType(clazz);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            ps.setString(i, JsonUtils.toNoNullJsonStr(parameter));
        } else {
            String value = parameter.stream().map(x -> (BaseDomain) x).map(BaseDomain::getId).collect(Collectors.joining(
                    ","));
            ps.setString(i, value);
        }
    }

    @Override
    public List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String value = rs.getString(columnName);
        if (value == null) {
            return null;
        }
        List<T> result = new LinkedList<>();
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            List<T> ts = JsonUtils.readValue(value, new TypeReference<List<T>>() {
            });
            if (ts != null) {
                ts.forEach(x -> {
                    T t = JsonUtils.convertValue(x, clazz);
                    if(null == t){
                        // throw RuntimeException
                    } else {
                        result.add(t);
                    }
                });
                return result;
            }
        } else {
            String[] ids = value.split(",");
            for (int i = 0, l = ids.length; i < l; i++) {
                result.add(JsonUtils.readValue(String.format(JsonTypeHandler.ID_TEMPLATE, ids[i]), clazz));
            }
            return result;
        }
        return null;
    }

    @Override
    public List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String value = rs.getString(columnIndex);
        if (value == null) {
            return null;
        }
        List<T> result = new LinkedList<>();
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            List<T> ts = JsonUtils.readValue(value, new TypeReference<List<T>>() {
            });
            if (ts != null) {
                ts.forEach(x -> {
                    T t = JsonUtils.convertValue(x, clazz);
                    if(null == t){
                        // throw RuntimeException
                    } else {
                        result.add(t);
                    }
                });
                return result;
            }
        } else {
            String[] ids = value.split(",");
            for (int i = 0, l = ids.length; i < l; i++) {
                result.add(JsonUtils.readValue(String.format(JsonTypeHandler.ID_TEMPLATE, ids[i]), clazz));
            }
            return result;
        }
        return null;
    }

    @Override
    public List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value = cs.getString(columnIndex);
        if (value == null) {
            return null;
        }
        List<T> result = new LinkedList<>();
        if (DwDaoHandler.Type.JSON.equals(type)) { // JSON
            List<T> ts = JsonUtils.readValue(value, new TypeReference<List<T>>() {
            });
            if (ts != null) {
                ts.forEach(x -> {
                    T t = JsonUtils.convertValue(x, clazz);
                    if(null == t){
                        // throw RuntimeException
                    } else {
                        result.add(t);
                    }
                });
                return result;
            }
        } else {
            String[] ids = value.split(",");
            for (int i = 0, l = ids.length; i < l; i++) {
                result.add(JsonUtils.readValue(String.format(JsonTypeHandler.ID_TEMPLATE, ids[i]), clazz));
            }
            return result;
        }
        return null;
    }

}

是否启用该序列化方式注解@EnableDwDaoHandler


import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 是否启用dreawerDaoHandler序列化到数据库
 * 使用该注解后即启用成功。
 * 默认扫描Mybatis.typeAliasesPackage别名包旗下所有使用@DwDaoHandler的属性。
 *
 * @author Leo.Xi
 * @date 2020/1/10
 * @since 1.0
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({DwMybatisConfig.class})
public @interface EnableDwDaoHandler {

}

声名式注解@DwDaoHandler


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * mybatis - DAO,Handler
 *
 * <p>使用须知:<p/> 2020-01-13
 * 1、使用注解时Type = ID的类必须继承BaseDomain
 * 2、适用该注解的类,不能单独储存到数据库,一般是作为其他对象的属性存在的
 * 3、需要单独存储的,则需要转为Map,Insert。或者List批量插入也是可以的。<code>insert("add", obj2Map(user)) OR insert("addBatchList", users)</code>
 *
 * @author Leo.Xi
 * @date 2020/1/9
 * @since 1.0
 **/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DwDaoHandler {

    /** 序列化类型 */
    Type value() default Type.JSON;

    enum Type {
        /** 只保留ID */
        ID,
        /** 对象Json */
        JSON;
    }

}

自动扫描、自动注册配置DwMybatisConfig.java


import com.dreawer.domain.BaseDomain;
import com.dreawer.persistence.handler.JsonListTypeHandler;
import com.dreawer.persistence.handler.JsonTypeHandler;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashMap;

/**
 * MybatisConfig - 配置类
 *
 * @author Leo.Xi
 * @date 2019/12/19
 * @since 1.0
 **/
@Configuration
public class DwMybatisConfig {

    private static final PathMatchingResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();
    private static final SimpleMetadataReaderFactory REGISTER = new SimpleMetadataReaderFactory();
    private static final StandardEnvironment ENVIRONMENT = new StandardEnvironment();
    /** 需要使用JsonTypeHandle转换的 - 单个 */
    private static final LinkedHashMap<Class<?>, DwDaoHandler.Type> SINGLE = new LinkedHashMap<>();
    /** 需要使用JsonListTypeHandle转换的 - 集合 List */
    private static final LinkedHashMap<Class<?>, DwDaoHandler.Type> COLLECTIONS = new LinkedHashMap<>();

    @Autowired
    private MybatisProperties mybatisProperties;

    /**
     * 根据包路径,获取Class的资源路径
     *
     * @param packagePath 包路径
     * @return
     */
    private static String getResourcePath(String packagePath) {
        if (StringUtils.isEmpty(packagePath)) {
            packagePath = "./";
        }
        return ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(ENVIRONMENT.resolveRequiredPlaceholders(packagePath))
                + '/' + "**/*.class";
    }

    /**
     * 获取单个类型
     *
     * @param clazz clazz
     * @return @link DwDaoHandler.Type
     * @author Leo.Xi
     * @date 2020/1/10
     * @since 0.0.1
     */
    public static DwDaoHandler.Type getSingleType(Class<?> clazz) {
        return SINGLE.get(clazz);
    }

    /**
     * 获取集合类型
     *
     * @param clazz clazz
     * @return @link DwDaoHandler.Type
     * @author Leo.Xi
     * @date 2020/1/10
     * @since 0.0.1
     */
    public static DwDaoHandler.Type getCollectionType(Class<?> clazz) {
        return COLLECTIONS.get(clazz);
    }

    /**
     * 获取列表字段的真实类型,非集合的返回null
     *
     * @param f 字段属性
     * @return 非集合的返回null
     * @author Leo.Xi
     * @date 2020/1/13
     * @since 0.0.1
     */
    public static Class<?> getCollectionFieldType(Field f) {
        Class<?> fieldClass = f.getType();
        if (Collection.class.isAssignableFrom(fieldClass)) {
            Type genericType = f.getGenericType();
            Type actualTypeArgument = ((ParameterizedType) genericType).getActualTypeArguments()[0];
            if (actualTypeArgument instanceof Class) {
                return (Class<?>) actualTypeArgument;
            }
        }
        return null;
    }

    /**
     * 获取指定路径下的类
     *
     * @param pkgPath 包路径
     */
    private static void scanMybatisHandler(String pkgPath) {
        //获取spring的包路径
        String pathPackage = getResourcePath(pkgPath);
        Resource[] resources = new Resource[0];
        try {
            //加载路径
            resources = RESOLVER.getResources(pathPackage);
        } catch (IOException e) {
            // ignore
        }

        MetadataReader metadataReader = null;
        Field[] fields;
        String className;
        for (int i = 0; i < resources.length; i++) {
            Resource resource = resources[i];
            try {
                //读取资源
                metadataReader = REGISTER.getMetadataReader(resource);
                //读取资源的注解配置
                AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                className = annotationMetadata.getClassName();
                fields = ClassUtils.forName(className, RESOLVER.getClassLoader()).getDeclaredFields();
            } catch (IOException | ClassNotFoundException e) {
                continue;
            }

            for (Field field : fields) {
                field.setAccessible(true);

                DwDaoHandler annotation = field.getAnnotation(DwDaoHandler.class);
                if (null != annotation) {
                    DwDaoHandler.Type type = annotation.value();
                    Class<?> fieldClass = field.getType();

                    if (Collection.class.isAssignableFrom(fieldClass)) {
                        Type genericType = field.getGenericType();
                        Type actualTypeArgument = ((ParameterizedType) genericType).getActualTypeArguments()[0];
                        if (actualTypeArgument instanceof Class) {
                            Class<?> aClass = (Class<?>) actualTypeArgument;
                            // 校验规则
                            if (DwDaoHandler.Type.ID.equals(type) && !BaseDomain.class.isAssignableFrom(aClass)) {
                                throw new RuntimeException(String.format("ID的序列化方式对象[%s]必须是BaseDomain的子类", aClass));
                            }
                            if (COLLECTIONS.containsKey(aClass)) {
                                // 比对类型是否一致
                                if (COLLECTIONS.get(aClass).equals(type)) {
                                    throw new RuntimeException(String.format("%s.%s的序列化方式存在不一致,请核实", className,
                                            field.getName()));
                                }
                            } else {
                                COLLECTIONS.put(aClass, type);
                            }
                        }
                    } else {
                        // 校验规则
                        if (DwDaoHandler.Type.ID.equals(type) && !BaseDomain.class.isAssignableFrom(fieldClass)) {
                            throw new RuntimeException(String.format("ID的序列化方式对象[%s]必须是BaseDomain的子类", fieldClass));
                        }
                        if (SINGLE.containsKey(fieldClass)) {
                            // 比对类型是否一致
                            if (SINGLE.get(fieldClass).equals(type)) {
                                throw new RuntimeException(String.format("%s.%s的序列化方式存在不一致,请核实", className,
                                        field.getName()));
                            }
                        } else {
                            SINGLE.put(fieldClass, type);
                        }
                    }
                }
            }

        }
    }

    /**
     * 自定义sqlSession 配置
     *
     * @param dataSource 数据源
     * @return SqlSessionFactory
     * @author Leo.Xi
     * @date 2019/12/19
     * @since 0.0.1
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Autowired DataSource dataSource) throws Exception {
        // 先扫描项目下的所有需要TypeHandler的类
        String typeAliasesPackage = mybatisProperties.getTypeAliasesPackage();
        if (typeAliasesPackage != null) {
            String[] split = typeAliasesPackage.split(",; \t\n");
            for (String pkg : split) {
                scanMybatisHandler(pkg);
            }
        }

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();

        sessionFactory.setDataSource(dataSource);
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        for (Class<?> clazz : SINGLE.keySet()) {
            configuration.getTypeHandlerRegistry().register(clazz, JsonTypeHandler.class);
        }
        for (Class<?> clazz : COLLECTIONS.keySet()) {
            configuration.getTypeHandlerRegistry().register(new JsonListTypeHandler<>(clazz));
        }
        // 控制台打印sql
        configuration.setLogImpl(org.apache.ibatis.logging.stdout.StdOutImpl.class);
        sessionFactory.setConfiguration(configuration);
        sessionFactory.setPlugins(new Interceptor[]{new DwDaoHandlerPlugin()});

//        System.err.println("mybatisProperties.getTypeAliasesPackage():" + mybatisProperties.getTypeAliasesPackage());
        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        //解决myBatis下 不能嵌套jar文件的问题
        VFS.addImplClass(SpringBootVFS.class);
//        VFS.addImplClass(JBoss6VFS.class);
        String[] mapperLocations = mybatisProperties.getMapperLocations();
        for (String mapperLocation : mapperLocations) {
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocation));
        }
        return sessionFactory.getObject();
    }

}

Mybatis插件DwDaoHandlerPlugin.java实现动态修正泛型对应的TypeHandler


import com.dreawer.persistence.handler.JsonListTypeHandler;
import com.dreawer.persistence.handler.JsonTypeHandler;
import com.dreawer.persistence.utils.GenericsUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.defaults.DefaultSqlSession;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.*;

/**
 * @author Leo.Xi
 * @Intercepts 拦截器注解,包括一个或多个 @Signature
 * @Signature 拦截的目标类信息,包括 type、method、args
 * type 要拦截的接口类型
 * method 接口中的方法名
 * args 方法的所有入参类型
 * @date 2020/1/11
 * @since 1.0
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class DwDaoHandlerPlugin implements Interceptor {

    /** 用户缓存对象的所有字段 */
    private static final LruCache<Class, List<Field>> CACHE_CLASS_FIELDS = new LruCache<>(256);

    /**
     * 反射获取类的所有字段,包含继承的字段
     *
     * @author Leo.Xi
     * @date 2020/1/13
     * @since 0.0.1
     */
    private static List<Field> getAllFields(Class clazz) {
        if (CACHE_CLASS_FIELDS.containsKey(clazz)) {
            return CACHE_CLASS_FIELDS.get(clazz);
        }
        List<Field> allFields = GenericsUtils.getAllFields(clazz, false, false);
        CACHE_CLASS_FIELDS.put(clazz, allFields);
        return allFields;
    }

    /**
     * 拦截目标对象的目标方法的执行,将自定义逻辑写在该方法中
     */
    @SuppressWarnings("unchecked")
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
//        System.out.println("ExamplePlugin...intercept:" + invocation.getMethod());

        // MetaObject 是 Mybatis 提供的一个用于访问对象属性的对象
        MetaObject metaObject = SystemMetaObject.forObject(invocation);

//        System.out.println("当前拦截到的对象:" + metaObject.getValue("target"));
//        System.out.println("SQL语句:" + metaObject.getValue("target.delegate.boundSql.sql"));
//        System.out.println("SQL语句类型:" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.sqlCommandType"));
        Object value = metaObject.getValue("target.delegate.parameterHandler.mappedStatement.sqlCommandType");
        String sqlType = null;
        if (null != value) {
            sqlType = value.toString();
        }
        if (null == sqlType) { // 不做任何处理
            // 返回执行结果
            return invocation.proceed();
        }
//        Configuration configuration = (Configuration) metaObject.getValue("target.delegate.configuration");
        BoundSql boundSql = (BoundSql) metaObject.getValue("target.delegate.boundSql");
        Object parameterObject = boundSql.getParameterObject();

        Class<?> parameterObjectClass = parameterObject.getClass();

        List<Field> allFields = getAllFields(parameterObjectClass);

        for (int i = 0; i < boundSql.getParameterMappings().size(); i++) {
            ParameterMapping parameterMapping = boundSql.getParameterMappings().get(i);

            if (parameterMapping.getTypeHandler() instanceof JsonTypeHandler) {// 单个对象的
                allFields.stream().filter(x -> x.getName().equals(parameterMapping.getProperty())).findFirst().ifPresent(c -> {
                    if (!parameterMapping.getJavaType().equals(c.getType())) {// 如果解析的类型不一致的话,自己设置
                        throw new RuntimeException("类型%s定制了JSON序列化方式故不能拥有自己的实体表结构,只能作为其他对象的属性,如若需要请转为Map插入或者List" +
                                "批量插入即可。");
                    }
                });
            } else if (parameterMapping.getTypeHandler() instanceof JsonListTypeHandler) { // 处理列表Json序列化的
                Class clazz = null;
                if (DefaultSqlSession.StrictMap.class.isAssignableFrom(parameterObjectClass)) {
                    // TODO 后期在处理
                    Object val = ((Map) parameterObject).get("collection");
                    if (GenericsUtils.isCollection(val) && ((List) val).size() > 0) {
//                        clazz = ((List)val).get(0).getClass();
                    }
                } else if (Map.class.isAssignableFrom(parameterObjectClass)) {
                    // TODO 后期在处理
                } else {
                    Optional<Field> first = allFields.stream().filter(x -> x.getName().equals(parameterMapping.getProperty())).findFirst();
                    if (!first.isPresent()) {
                        continue;
                    }
                    Field f = first.get();
                    f.setAccessible(true);
                    clazz = DwMybatisConfig.getCollectionFieldType(f);
                }
                DwDaoHandler.Type type = DwMybatisConfig.getCollectionType(clazz);
                if (type != null) {
                    metaObject.setValue("target.delegate.boundSql.parameterMappings[" + i + "].typeHandler",
                            new JsonListTypeHandler<>(clazz));
                }
            }
        }
//        System.out.println("SQL语句入参:" + boundSql.getParameterObject());

        if (SqlCommandType.SELECT.name().equalsIgnoreCase(sqlType)) {// 查询语句需要处理入参、出参
            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("target.delegate.parameterHandler.mappedStatement");
            List<ResultMap> resultMaps = mappedStatement.getResultMaps(); // mapperXML 的resultMap映射表
            for (int i = 0; i < resultMaps.size(); i++) {
                final int row = i;
                ResultMap resultMap = resultMaps.get(i);

                allFields = getAllFields(resultMap.getType());
                for (int j = 0; j < resultMap.getResultMappings().size(); j++) {
                    final int index = j;
                    ResultMapping resultMapping = resultMap.getResultMappings().get(j);

                    if (resultMapping.getTypeHandler() instanceof JsonListTypeHandler) {
                        allFields.stream().filter(x -> x.getName().equals(resultMapping.getProperty())).findFirst().ifPresent(c -> {
                            Class clazz = DwMybatisConfig.getCollectionFieldType(c);
                            DwDaoHandler.Type type = DwMybatisConfig.getCollectionType(clazz);
                            if (type != null) {
                                metaObject.setValue("target.delegate.parameterHandler.mappedStatement.resultMaps[" + row + "]" +
                                                ".resultMappings[" + index + "].typeHandler",
                                        new JsonListTypeHandler<>(clazz));
                            }

                        });
                    }

                }
            }
        }

//        System.out.println("Mapper方法全路径名:" + metaObject.getValue("target.delegate.parameterHandler.mappedStatement.id"));

        // 返回执行结果
        return invocation.proceed();
    }

    /**
     * 为目标对象创建一个代理对象,使用 Plugin.wrap(target,this) 即可
     *
     * @param target 上次包装的代理对象
     * @return 本次包装过的代理对象
     */
    @Override
    public Object plugin(Object target) {
//        System.out.println("ExamplePlugin...plugin:" + target);
        return Plugin.wrap(target, this);
    }

    /**
     * 获取自定义配置参数
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
//        System.out.println("插件配置信息:" + properties);
//        System.out.println("someProperty:" + properties.get("someProperty"));
    }

    /**
     * LRU为Least Recently Used的缩写,意思也就是近期最少使用算法。
     *
     * @author Leo.Xi
     * @date 2020/1/13
     * @since 0.0.1
     */
    public static class LruCache<K, V> extends LinkedHashMap<K, V> {

        int capacity = 256; // 最大容量 - 不能超过它

        public LruCache(int capacity) {
            super(capacity, 0.75f, true);
            this.capacity = capacity;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry eldest) {
            if (size() > this.capacity) {
                return true;
            }
            return false;
        }
    }
}

后期需要的,只需要在这基础上修改一下,即可使用。
记录一下最近的实现。2020-01-13写
也希望能够帮助到你。

Leo、Xi 发布了3 篇原创文章 · 获赞 2 · 访问量 100 私信 关注

标签:return,自定义,TypeHandler,Type,clazz,自动,org,import,type
来源: https://blog.csdn.net/h785160953/article/details/103962069