Hibernateを使ってJSONオブジェクトを永続化する

Hibernateを使用してJSONオブジェクトを永続化する

1. 概要

一部のプロジェクトでは、JSONオブジェクトをリレーショナルデータベースに永続化する必要があります。

このチュートリアルでは、take a JSON object and persist it in a relational databaseを実行する方法を説明します。

この機能を提供する利用可能なフレームワークはいくつかありますが、HibernateJacksonのみを使用するいくつかの単純で一般的なオプションを見ていきます。

2. 依存関係

このチュートリアルでは、basic Hibernate Core dependencyを使用します。


    org.hibernate
    hibernate-core
    5.4.0.Final

また、JSONライブラリとしてJacksonを使用します。


    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);
}

永続化する前にこのメソッドを手動で呼び出すことも、属性が更新されるたびにJSON文字列も更新されるようにsetCustomerAttributesメソッドから呼び出すこともできます。 

次に、データベースからCustomerを取得するときのwe’ll create a method to deserialize the JSON string back into a HashMap object

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;
    }

}

次に、customerAttributesフィールドに新しいAttributeConverterを使用するようにHibernateに指示します。これで完了です。

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

With this approach, we no longer have to manually call the serialize and deserialize methods sinceHibernateがそれを処理してくれます。 通常、Customerオブジェクトを保存および取得するだけです。

5. 結論

この記事では、HibernateとJacksonを使用してJSONオブジェクトを永続化する方法の例をいくつか見てきました。

最初の例では、カスタムのシリアライズおよびデシリアライズメソッドを使用した、シンプルで互換性のあるメソッドを検討しました。 次に、コードを単純化する強力な方法としてAttributeConvertersを導入しました。

いつものように、このチュートリアルover on Githubのソースコードを確認してください。