Сохранять объект JSON, используя Hibernate

Сохранение объекта JSON с использованием Hibernate

1. обзор

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

В этом руководстве мы увидим, какtake a JSON object and persist it in a relational database.

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

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

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


    org.hibernate
    hibernate-core
    5.4.0.Final

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


    com.fasterxml.jackson.core
    jackson-databind
    2.9.8

Note that these techniques are not limited to these two libraries. Мы можем заменить наш любимый поставщик JPA и библиотеку JSON.

3. Сериализация и десериализация методов

Самый простой способ сохранить объект JSON в реляционной базе данных - этоconvert the object into a String перед его сохранением. Затем мыconvert it back into an object, когда получаем его из базы данных.

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

Первое, что мы рассмотрим, - этоcustom serialize and deserialize methods.

Мы начнем с простой сущности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;
}

Вместо того, чтобы сохранять атрибуты в отдельной таблице, мы перейдем кstore them as JSON in a column in the Customers table. Это может помочь уменьшить сложность схемы и повысить производительность запросов.

Во-первых,we’ll create a serialize method that will take our customerAttributes and convert it to a JSON string:

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

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

Затемwe’ll create a method to deserialize the JSON string back into a HashMap object, когда мы извлекаемCustomer из базы данных:

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. Конвертер атрибутов

If we are using JPA 2.1 or higher, мы можем использоватьAttributeConverters для оптимизации этого процесса.

Сначала мы создадим реализацию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 для поляcustomerAttributes, и все готово:

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

With this approach, we no longer have to manually call the serialize and deserialize methods s, поскольку Hibernate позаботится об этом за нас. Мы можем просто сохранить и получить объектCustomer в обычном режиме.

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

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

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

Как всегда, обязательно ознакомьтесь с исходным кодом этого руководстваover on Github.