Spring JPA的实体属性类型转换器并反序列化工具类详解
作者:Y7000也拯救不了我
这篇文章主要介绍了Spring JPA的实体属性类型转换器并反序列化工具类详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
一、JPA 单体JSON与Map的映射
数据库中test字段为json类型
{"key": "颜色", "value": "深白色", "key_id": 1, "value_id": 3}
模型中test字段为Map类型
private Map<String,Object> test;
问题:如何将数据库字段的值映射到模型中,要用到JPA的属性转换
创建一个转换类
实现AttributeConverter接口
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.lin.missyou.exception.http.ServerErrorException; import org.springframework.beans.factory.annotation.Autowired; import javax.persistence.AttributeConverter; import javax.persistence.Convert; import javax.persistence.Converter; import java.util.HashMap; import java.util.Map; // 第一个泛型类型就是 entity字段的类型 // json没有类型,对应在JAVA中就是String类型 // 第二个泛型类型就是 数据库字段的类型 @Converter public class MapAndJson implements AttributeConverter<Map<String, Object>, String> { /* ObjectMapper类是Jackson库的主要类,它提供一些功能将数据集或对象转换的实现。 它将使用JsonParser和JsonGenerator实例来实现JSON的实际读/写。 */ @Autowired private ObjectMapper mapper; @Override public String convertToDatabaseColumn(Map<String, Object> map) { try { return mapper.writeValueAsString(map); } catch (Exception e) { e.printStackTrace(); throw new ServerErrorException(99999); } } @Override @SuppressWarnings("unchecked") public Map<String, Object> convertToEntityAttribute(String s) { try { if (s == null) return null; return mapper.readValue(s, HashMap.class); } catch (Exception e) { e.printStackTrace(); throw new ServerErrorException(9999); } } }
看到接口的方法名,就知道能做什么了。
具体转换需要自己实现,调用SpringBoot提供的Jackson的内置库。
ObjectMapper类是Jackson库的主要类,它提供一些功能将数据集或对象转换的实现。
在类上打上注解@Converter,做为转换类的标识。
只需在模型类上加个注解就能完成自动转换
指明转换类
@Convert(converter = MapAndJson.class) private Map<String,Object> test;
其他类型转换的操作基本一致,只需要修改类型等局部代码。
二、封装反序列化工具类
数据库中specs字段为json类型
[{"key": "颜色", "value": "深白色", "key_id": 1, "value_id": 3}, {"key": "尺寸", "value": "4.3英寸", "key_id": 2, "value_id": 7}]
模型中specs字段为String类型
建立Spec实体类
@Getter @Setter public class Spec { private Long keyId; private String key; private Long valueId; private String value; }
利用JPA的AttributeConverter接口实现属性转换过于局限
模仿JPA的AttributeConverter接口封装两个方法。
希望转换为实体类的本类型,因为默认将json数据转换为LinkHashMap类型。
通用的转换类,转换为本类。
//反序列化工具类 @Component public class GenericAndJson { private static ObjectMapper mapper; //将ObjectMapper注入到方法里,再通过方法赋值到成员变量上 @Autowired public void setMapper(ObjectMapper mapper) { GenericAndJson.mapper = mapper; } public static <T> String objectToJson(T o) { try { return GenericAndJson.mapper.writeValueAsString(o); } catch (Exception e) { e.printStackTrace(); throw new ServerErrorException(99999); } } public static <T> T jsonToObject(String s, TypeReference<T> typeReference) { if (s == null) return null; try { return GenericAndJson.mapper.readValue(s, typeReference); } catch (Exception e) { e.printStackTrace(); throw new ServerErrorException(9999); } } }
如何调用自定义的转换器
在实体类中,可以通过重写getter、setter方法,自己实现想要转换的数据结构(List),本且能够得到本类(Spec)。
private String specs; public List<Spec> getSpecs() { if (specs == null) return Collections.emptyList(); return GenericAndJson.jsonToObject(this.specs, new TypeReference<List<Spec>>() {}); } public void setSpecs(List<Spec> specs) { if (specs.isEmpty()) return; this.specs = GenericAndJson.objectToJson(specs); }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。