千家信息网

Spring JPA repository怎样自定义数据converter

发表于:2025-01-30 作者:千家信息网编辑
千家信息网最后更新 2025年01月30日,本篇文章为大家展示了Spring JPA repository怎样自定义数据converter,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。我们都知道在使用j
千家信息网最后更新 2025年01月30日Spring JPA repository怎样自定义数据converter

本篇文章为大家展示了Spring JPA repository怎样自定义数据converter,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

我们都知道在使用jpaRepository 里边的方法时,返回的数据格式要么是和数据库表映射的entity,要么是 Projection 接口,或者map,或者基本数据类型。如果想要自定义一个类来接收数据的话,就会抛出类型转换错误。有了需求就有了动力。

最近在做项目的时候,想复用vo类来接收 Repository的返回数据,可是spirngjpa不认,于是在百度一通无果后,开始debug执行过程。功夫不负有心人,找到了数据转换的方法。一切奥妙都在这个类里边 DefaultConversionService ,如下部分截图

也就说如果我自定义一个converter 并且把它注册到这个ConversionService 里边,那我就可以在我自己的convert里边'猥琐'欲为..

首先看截图的第一个方法,顾名思义 可以获取到他的共享的实例!这就很明显了,就是给我们开的一扇窗呀。话不多说,下面就是使用方法 和 我自定义的convert

//springboot 启动类    public static void main(String[] args) {        SpringApplication.run(Application.class, args);        ((DefaultConversionService) DefaultConversionService.getSharedInstance())                .addConverter(new MyConverter());    }//MyConverter.javaimport lombok.extern.slf4j.Slf4j;import org.springframework.core.convert.TypeDescriptor;import org.springframework.core.convert.converter.GenericConverter;import org.springframework.util.ConcurrentReferenceHashMap;import sun.reflect.misc.MethodUtil;import java.lang.reflect.Method;import java.math.BigInteger;import java.util.HashSet;import java.util.Map;import java.util.Set;import java.util.stream.Stream;/** * .自定义 对象转换器 *  */@Slf4jpublic class RdeConverter implements GenericConverter {    private final Map methodCache = new ConcurrentReferenceHashMap<>(2 >> 6);    private final CacheMethod NO_MATCH = new CacheMethod(null);    @Override    public Set getConvertibleTypes() {        ConvertiblePair pair = new ConvertiblePair(Map.class, RdeConvertible.class);        Set set = new HashSet<>();        set.add(pair);        return set;    }    @Override    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {        try {            log.debug("***begin convert {} to {}", sourceType, targetType);            Map map = (Map) source;            Object o = targetType.getType().newInstance();            for (Object fieldName : map.keySet()) {                String name = getMethodName(fieldName.toString());                String mName = o.getClass().getName().concat(".").concat(name);                CacheMethod cacheMethod = methodCache.get(mName);                if (cacheMethod == null) {                    //FIXME  如果存在方法重载 ,可能会存在异常                    Method method = Stream.of(MethodUtil.getPublicMethods(targetType.getType()))                            .filter(m -> m.getName().equalsIgnoreCase(name))                            .findFirst().orElse(null);                    cacheMethod = method == null ? NO_MATCH : new CacheMethod(method);                    methodCache.put(mName, cacheMethod);                }                if (cacheMethod != NO_MATCH) {                    try {                        Method method = cacheMethod.get();                        method.invoke(o, caseParam(map.get(fieldName), method.getParameterTypes()[0]));                    } catch (Exception e) {                        log.error(e.getMessage(), e);                    }                }            }            return o;        } catch (Exception e) {            log.error(e.getMessage(), e);        }        return null;    }    private Object caseParam(Object param, Class paramType) {        if (param instanceof BigInteger) {            if (param.getClass() == paramType) {                return param;            }            if (paramType == Integer.class) {                return ((BigInteger) param).intValue();            }            if (paramType == Long.class) {                return ((BigInteger) param).longValue();            }            return param;        }        return param;    }    private String getMethodName(String fieldName) {        String[] s = fieldName.trim().split("_");        if (s.length > 1) {            String m = Stream.of(s).reduce((a, b) -> firstToUp(a) + firstToUp(b)).get();            return "set".concat(m);        }        return "set".concat(firstToUp(s[0]));    }    private String firstToUp(String s) {        if (s.length() > 1) {            return s.substring(0, 1).toUpperCase().concat(s.substring(1));        }        return s.toUpperCase();    }    class CacheMethod {        private Method method;        CacheMethod(Method method) {            this.method = method;        }        Method get() {            return this.method;        }    }}//RdeConvertible.java/** * .转换类型标记 * */public interface RdeConvertible {}

使用截图:

上述内容就是Spring JPA repository怎样自定义数据converter,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

0