将 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:52:09  来源:igfitidea点击:

Map JSON string column of a JPA entity to Java object automatically

javajsonjpaHymanson

提问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>>() {})
 }
}