Рубрики
Без рубрики

Сохранение объекта JSON с помощью Hibernate

Узнайте, как преобразователи атрибутов облегчают сохранение объектов JSON в спящем режиме.

Автор оригинала: baeldung.

1. Обзор

В некоторых проектах может потребоваться сохранение объектов JSON в реляционной базе данных.

В этом уроке мы увидим, как взять объект JSON и сохранить его в реляционной базе данных .

Существует несколько фреймворков, обеспечивающих эту функциональность, но мы рассмотрим несколько простых, общих опций, использующих только Hibernate и Jackson .

2. Зависимости

Мы будем использовать зависимость basic Hibernate Core для этого урока:


    org.hibernate
    hibernate-core
    5.4.0.Final

Мы также будем использовать Jackson в качестве нашей библиотеки JSON:


    com.fasterxml.jackson.core
    jackson-databind
    2.9.8

Обратите внимание, что эти методы не ограничиваются этими двумя библиотеками. Мы можем заменить ваш любимый поставщик JPA и библиотеку JSON.

3. Методы сериализации и десериализации

Самый простой способ сохранить объект JSON в реляционной базе данных-это преобразовать объект в Строку перед его сохранением. Затем мы преобразуем его обратно в объект , когда мы извлекаем его из базы данных.

Мы можем сделать это несколькими различными способами.

Первый, который мы рассмотрим, – это использование пользовательских методов сериализации и десериализации.

Мы начнем с простой сущности Customer , которая хранит имя и фамилию клиента, а также некоторые атрибуты этого клиента.

Стандартный объект JSON будет представлять эти атрибуты в виде HashMap , так что это то, что мы будем использовать здесь:

@Entity
@Table(name = "Customers")
public class Customer {

    @Id
    private int id;

    private String firstName;

    private String lastName;

    private String customerAttributeJSON;

    @Convert(converter = HashMapConverter.class)
    private Map customerAttributes;
}

Вместо того, чтобы сохранять атрибуты в отдельной таблице, мы собираемся сохранить их в виде JSON в столбце в таблице Customers . Это может помочь снизить сложность схемы и повысить производительность запросов.

Во-первых, мы создадим метод сериализации, который будет принимать наши атрибуты клиента и преобразовывать его в строку JSON :

public void serializeCustomerAttributes() throws JsonProcessingException {
    this.customerAttributeJSON = objectMapper.writeValueAsString(customerAttributes);
}

Мы можем вызвать этот метод вручную перед сохранением, или мы можем вызвать его из метода set Customer Attributes , чтобы при каждом обновлении атрибутов также обновлялась строка JSON.

Далее, мы создадим метод для десериализации строки JSON обратно в HashMap объект при извлечении Клиента из базы данных:

public void deserializeCustomerAttributes() throws IOException {
    this.customerAttributes = objectMapper.readValue(customerAttributeJSON, HashMap.class);
}

Опять же, есть несколько разных мест, из которых мы можем вызвать этот метод, но в этом примере мы вызовем его вручную.

Итак, сохранение и извлечение нашего объекта Customer будет выглядеть примерно так:

@Test
public void whenStoringAJsonColumn_thenDeserializedVersionMatches() {
    Customer customer = new Customer();
    customer.setFirstName("first name");
    customer.setLastName("last name");

    Map attributes = new HashMap<>();
    attributes.put("address", "123 Main Street");
    attributes.put("zipcode", 12345);

    customer.setCustomerAttributes(attributes);
    customer.serializeCustomerAttributes();

    String serialized = customer.getCustomerAttributeJSON();

    customer.setCustomerAttributeJSON(serialized);
    customer.deserializeCustomerAttributes();

    assertEquals(attributes, customer.getCustomerAttributes());
}

4. Конвертер атрибутов

Если мы используем JPA 2.1 или выше , мы можем использовать Преобразователи атрибутов для оптимизации этого процесса.

Во-первых, мы создадим реализацию AttributeConverter . Мы будем повторно использовать наш код из предыдущих версий:

public class HashMapConverter implements AttributeConverter, String> {

    @Override
    public String convertToDatabaseColumn(Map customerInfo) {

        String customerInfoJson = null;
        try {
            customerInfoJson = objectMapper.writeValueAsString(customerInfo);
        } catch (final JsonProcessingException e) {
            logger.error("JSON writing error", e);
        }

        return customerInfoJson;
    }

    @Override
    public Map convertToEntityAttribute(String customerInfoJSON) {

        Map customerInfo = null;
        try {
            customerInfo = objectMapper.readValue(customerInfoJSON, Map.class);
        } catch (final IOException e) {
            logger.error("JSON reading error", e);
        }

        return customerInfo;
    }

}

Затем мы говорим Hibernate использовать наш новый AttributeConverter для поля Атрибуты клиента , и мы закончили:

@Convert(converter = HashMapConverter.class)
private Map customerAttributes;

При таком подходе нам больше не нужно вручную вызывать методы сериализации и десериализации , так как Hibernate позаботится об этом за нас. Мы можем просто сохранить и получить объект Customer в обычном режиме.

5. Заключение

В этой статье мы рассмотрели несколько примеров сохранения объектов JSON с помощью Hibernate и Jackson.

В нашем первом примере рассматривался простой, совместимый метод, использующий пользовательские методы сериализации и десериализации. И во-вторых, мы представили Преобразователи атрибутов как мощный способ упростить наш код.

Как всегда, не забудьте проверить исходный код этого учебника на Github .