Spring?JPA的實(shí)體屬性類型轉(zhuǎn)換器并反序列化工具類詳解
一、JPA 單體JSON與Map的映射
數(shù)據(jù)庫(kù)中test字段為json類型
{"key": "顏色", "value": "深白色", "key_id": 1, "value_id": 3}模型中test字段為Map類型
private Map<String,Object> test;
問(wèn)題:如何將數(shù)據(jù)庫(kù)字段的值映射到模型中,要用到JPA的屬性轉(zhuǎn)換
創(chuàng)建一個(gè)轉(zhuǎn)換類
實(shí)現(xiàn)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;
// 第一個(gè)泛型類型就是 entity字段的類型
// json沒(méi)有類型,對(duì)應(yīng)在JAVA中就是String類型
// 第二個(gè)泛型類型就是 數(shù)據(jù)庫(kù)字段的類型
@Converter
public class MapAndJson implements AttributeConverter<Map<String, Object>, String> {
/*
ObjectMapper類是Jackson庫(kù)的主要類,它提供一些功能將數(shù)據(jù)集或?qū)ο筠D(zhuǎn)換的實(shí)現(xiàn)。
它將使用JsonParser和JsonGenerator實(shí)例來(lái)實(shí)現(xiàn)JSON的實(shí)際讀/寫。
*/
@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);
}
}
}
看到接口的方法名,就知道能做什么了。
具體轉(zhuǎn)換需要自己實(shí)現(xiàn),調(diào)用SpringBoot提供的Jackson的內(nèi)置庫(kù)。
ObjectMapper類是Jackson庫(kù)的主要類,它提供一些功能將數(shù)據(jù)集或?qū)ο筠D(zhuǎn)換的實(shí)現(xiàn)。
在類上打上注解@Converter,做為轉(zhuǎn)換類的標(biāo)識(shí)。
只需在模型類上加個(gè)注解就能完成自動(dòng)轉(zhuǎn)換
指明轉(zhuǎn)換類
@Convert(converter = MapAndJson.class) private Map<String,Object> test;
其他類型轉(zhuǎn)換的操作基本一致,只需要修改類型等局部代碼。
二、封裝反序列化工具類
數(shù)據(jù)庫(kù)中specs字段為json類型
[{"key": "顏色", "value": "深白色", "key_id": 1, "value_id": 3}, {"key": "尺寸", "value": "4.3英寸", "key_id": 2, "value_id": 7}]模型中specs字段為String類型
建立Spec實(shí)體類
@Getter
@Setter
public class Spec {
private Long keyId;
private String key;
private Long valueId;
private String value;
}
利用JPA的AttributeConverter接口實(shí)現(xiàn)屬性轉(zhuǎn)換過(guò)于局限
模仿JPA的AttributeConverter接口封裝兩個(gè)方法。
希望轉(zhuǎn)換為實(shí)體類的本類型,因?yàn)槟J(rèn)將json數(shù)據(jù)轉(zhuǎn)換為L(zhǎng)inkHashMap類型。
通用的轉(zhuǎn)換類,轉(zhuǎn)換為本類。
//反序列化工具類
@Component
public class GenericAndJson {
private static ObjectMapper mapper;
//將ObjectMapper注入到方法里,再通過(guò)方法賦值到成員變量上
@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);
}
}
}
如何調(diào)用自定義的轉(zhuǎn)換器
在實(shí)體類中,可以通過(guò)重寫getter、setter方法,自己實(shí)現(xiàn)想要轉(zhuǎn)換的數(shù)據(jù)結(jié)構(gòu)(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);
}以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式)
這篇文章主要介紹了基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
MybatisPlus多數(shù)據(jù)源及事務(wù)解決思路
這篇文章主要介紹了MybatisPlus多數(shù)據(jù)源及事務(wù)解決思路,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
一個(gè)簡(jiǎn)易的Java多頁(yè)面隊(duì)列爬蟲程序
這篇文章主要為大家詳細(xì)介紹了一個(gè)多頁(yè)面的java爬蟲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08
解決定時(shí)任務(wù)@Scheduled沒(méi)有準(zhǔn)時(shí)執(zhí)行的原因及分析
這篇文章主要介紹了解決定時(shí)任務(wù)@Scheduled沒(méi)有準(zhǔn)時(shí)執(zhí)行的原因及分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)
這篇文章主要為大家介紹了httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)解讀*,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
java動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理示例分享
這篇文章主要介紹了java動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理示例,JDK1.3之后,Java提供了動(dòng)態(tài)代理的技術(shù),允許開(kāi)發(fā)者在運(yùn)行期間創(chuàng)建接口的代理實(shí)例,下面我們使用示例學(xué)習(xí)一下2014-03-03
Spring?Boot整合阿里開(kāi)源中間件Canal實(shí)現(xiàn)數(shù)據(jù)增量同步
這篇文章主要為大家介紹了Spring?Boot整合阿里開(kāi)源中間件Canal實(shí)現(xiàn)數(shù)據(jù)增量同步示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06

