本篇文章为大家展示了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.java
import 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;
/**
* .自定义 对象转换器
*
*/
@Slf4j
public class RdeConverter implements GenericConverter {
private final Map<String, CacheMethod> methodCache = new ConcurrentReferenceHashMap<>(2 >> 6);
private final CacheMethod NO_MATCH = new CacheMethod(null);
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
ConvertiblePair pair = new ConvertiblePair(Map.class, RdeConvertible.class);
Set<ConvertiblePair> 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,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/xiwanglr/blog/3067928