发布于 1年前

JPA JSON字符串与List以及对象的转换

有时为了方便,我们会吧对象或者List以JSON字符串的形式存放在数据库中。使用JPA就可以通过@Converte的方式实现。

JSON字符与对象的转换,我们比较常用的时jackson,maven依赖如下:

<dependencies>
     <!--加入jackson库-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.0</version>
    </dependency>
  </dependencies>

JSONObject字符串转换为对象

这里以Order和Metadata为例。

1、首先创建用于转换Metadata对象的转换器。

@Converter(autoApply = true)
public class JSONConverter implements AttributeConverter<Metadata, String> {
    private final static Logger LOGGER = LoggerFactory.getLogger(JSONConverter .class);
    private final static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(Metadata meta) {
        try {
            return objectMapper.writeValueAsString(meta);
        } catch (JsonProcessingException ex) {
            LOGGER.error("", ex);
            return null;
        }
    }

    @Override
    public Metadata convertToEntityAttribute(String dbData) {
        try {
            return objectMapper.readValue(dbData, Metadata.class);
        } catch (IOException ex) {
            LOGGER.error("", ex);
            return null;
        }
    }
}

代码实现了JPA转换器接口AttributeConverter,这个接口提供了两个方法:

  • convertToDatabaseColumn:用于把对象转换为数据库字段存储的值。
  • convertToEntityAttribute:用于把数据库里的字段存储的值转换为对象。

在convertToDatabaseColumn方法中,使用了Jackson的ObjectMapper的writeValuAsString,把对象转换为JSONObject的字符串。

在convertToEntityAttribute方法中,也是用了Jackson的ObjectMapperreadValue方法,把字符串转换为对象。

2、在Order对象中添加注解@Convert

@Entity
@Table(name = "order")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Convert(converter = JSONConverter.class)
    private Metadata metadata;

    //…get 和set方法
}

JSONArray字符串转换为List

JSONArray与List之间的转换类似于对象的转换,但因为Jackson对List范类型的转换实现不同,所以在字符串转换List实现方式不同。

1、定义转换器

@Converter(autoApply = true)
public class OrderItemsJSONConverter implements AttributeConverter<List<OrderItem>, String> {

    private final static Logger LOGGER = LoggerFactory.getLogger(ChaptersJSONConverter.class);

    private final static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public String convertToDatabaseColumn(List<OrderItem> meta) {
        try {
            return objectMapper.writeValueAsString(meta);
        } catch (JsonProcessingException ex) {
            LOGGER.error("", ex);
            return null;
        }
    }

    @Override
    public List<OrderItem> convertToEntityAttribute(String dbData) {
        try {
            if(dbData == null){  //如果dbData为null会导致转换报错,可以根据业务需求对null做处理
                return new ArrayList<>();
            }
            return objectMapper.readValue(dbData, new TypeReference<List<OrderItem>>(){});
        } catch (IOException ex) {
            LOGGER.error("", ex);
            return null;
        }
    }

}

在字符串转换List,objectMapper.readValue的类型时TypeReference,这个是与对象转换不同的地方。

2、Order的OrderItem列表添加@Convert注释

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "order")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Convert(converter = JSONConverter.class)
    private Metadata metadata;

    @Convert(converter = ItemsJSONArrayConverter.class)
    private List<OrderItem> item;

    //get set方法
}
©2020 edoou.com   京ICP备16001874号-3