将 JPA 实体的 JSON 字符串列自动映射到 Java 对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35613527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Map JSON string column of a JPA entity to Java object automatically
提问by drunkenfist
I have a JPA entity object with following structure:
我有一个具有以下结构的 JPA 实体对象:
@Table(name="item_info")
class Item(){
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="item_name")
private String itemName;
@Column(name="product_sku")
private String productSku;
@Column(name="item_json")
private String itemJsonString;
@Transient
private ItemJson itemJson;
//Getters and setters
}
The itemJsonString field contains a json string value such as '{"key1":"value1","key2":"value2"}'
itemJsonString 字段包含一个 json 字符串值,例如 '{"key1":"value1","key2":"value2"}'
And the itemJson field contains the corresponding object which maps to the json string.
itemJson 字段包含映射到 json 字符串的相应对象。
I get this entity object from database as follows:
我从数据库中获取这个实体对象如下:
Item item = itemRepository.findOne(1L); // Returns item with id 1
Now, the itemJson field is null since it is a transient field. And I have to set it manually using Hymanson's ObjectMapper as follows:
现在, itemJson 字段为空,因为它是一个瞬态字段。我必须使用 Hymanson 的 ObjectMapper 手动设置它,如下所示:
itemJson = objectMapper.readValue(item.getItemJsonString(), ItemJson.class);
How can I make it such that when I do itemRepository.findOne(), it returns an Item object with the itemJson field mapped to the json String automatically?
我怎样才能做到这样,当我这样做时itemRepository.findOne(),它会返回一个 Item 对象,其中 itemJson 字段自动映射到 json 字符串?
采纳答案by stdunbar
Your best bet would be to implement a javax.persistence.Converter. It would look something like:
最好的办法是实现一个 javax.persistence.Converter。它看起来像:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<ItemJson, String> {
@Override
public String convertToDatabaseColumn(ItemJson entityValue) {
if( entityValue == null )
return null;
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(entityValue);
}
@Override
public ItemJson convertToEntityAttribute(String databaseValue) {
if( databaseValue == null )
return null;
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(databaseValue, ItemJson.class);
}
}
I've used this with WildFly and didn't have to do anything except have it be in the war file I was deploying.
我已经将它与 WildFly 一起使用,除了将它放在我正在部署的 war 文件中之外,什么都不用做。
回答by Petr Mensik
You could postLoad callbackfor manipulating entity after it's loaded. So try something like this inside your entity class
您可以在加载实体后使用postLoad回调来操作它。所以在你的实体类中尝试这样的事情
@PostLoad
public void afterLoad() {
ObjectMapper mapper = new ObjectMapper();
itemJson = mapper.readValue(item.getItemJsonString(), ItemJson.class);
}
回答by Munish Chandel
Here is the full working version of AttributeConverter+ JPA + Kotlin.
这是AttributeConverter+ JPA + Kotlin的完整工作版本。
Entity Class
实体类
In my case, database was mysql (8.x), which supports JSON as the underlying data type for column definition, and we can apply a custom converter using @Convertannotation.
在我的例子中,数据库是 mysql (8.x),它支持 JSON 作为列定义的底层数据类型,我们可以使用@Convert注释应用自定义转换器。
@Entity
data class Monitor (
@Id
val id: Long? = null,
@Column(columnDefinition = "JSON")
@Convert(converter = AlertConverter::class)
var alerts: List<Alert> = emptyList(),
var active: Boolean = false
)
Converter DefinitionAttribute converter needs to specify the conversion mechanism from data to db and reverse. We are using Hymanson to convert a java object into String format and vice versa.
Converter 定义属性converter 需要指定data 到db 和reverse 的转换机制。我们正在使用 Hymanson 将 java 对象转换为 String 格式,反之亦然。
@Converter(autoApply = true)
class AlertConverter : AttributeConverter<List<Alert>, String> {
private val objectMapper = ObjectMapper()
override fun convertToDatabaseColumn(data: List<Alert>?): String {
return if (data != null && !data.isEmpty())
objectMapper.writeValueAsString(data)
else ""
}
override fun convertToEntityAttribute(dbData: String?): List<Alert> {
if (StringUtils.isEmpty(dbData)) {
return emptyList()
}
return objectMapper.readValue(dbData, object : TypeReference<List<Alert>>() {})
}
}

