将 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 @Convert
annotation.
在我的例子中,数据库是 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>>() {})
}
}