繁体   English   中英

将JPA实体的JSON字符串列自动映射到Java对象

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

我有一个具有以下结构的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

}

itemJsonString字段包含json字符串值,例如'{"key1":"value1","key2":"value2"}'

并且itemJson字段包含对应的对象,该对象映射到json字符串。

我从数据库中获取此实体对象,如下所示:

Item item = itemRepository.findOne(1L);    // Returns item with id 1

现在,itemJson字段为空,因为它是一个瞬态字段。 而且我必须使用Jackson的ObjectMapper手动设置它,如下所示:

itemJson = objectMapper.readValue(item.getItemJsonString(), ItemJson.class);

我怎样才能做到,当我执行itemRepository.findOne() ,它返回一个Item对象,该对象的itemJson字段自动映射到json字符串?

最好的选择是实现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);

    }
}

我已经在WildFly中使用了它,除了将其保存在我正在部署的war文件中之外,无需执行任何操作。

这是AttributeConverter + JPA + Kotlin的完整版本。

实体类别

在我的情况下,数据库是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
)

转换器定义属性转换器需要指定从数据到db以及反向的转换机制。 我们正在使用Jackson将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>>() {})
 }
}

您可以在实体加载后通过postLoad 回调操作实体。 所以在您的实体类中尝试这样的事情

@PostLoad
public void afterLoad() {
    ObjectMapper mapper = new ObjectMapper();
    itemJson = mapper.readValue(item.getItemJsonString(), ItemJson.class);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM