Beharrung eines JSON-Objekts mit Ruhezustand

Beibehalten eines JSON-Objekts im Ruhezustand

1. Überblick

Bei einigen Projekten müssen JSON-Objekte möglicherweise in einer relationalen Datenbank gespeichert werden.

In diesem Tutorial erfahren Sie, wie Sietake a JSON object and persist it in a relational database ausführen.

Es gibt verschiedene Frameworks, die diese Funktionalität bereitstellen. Wir werden uns jedoch einige einfache, generische Optionen ansehen, bei denen nurHibernate undJackson verwendet werden.

2. Abhängigkeiten

Wir werden diebasic Hibernate Core dependency für dieses Tutorial verwenden:


    org.hibernate
    hibernate-core
    5.4.0.Final

Wir werden auchJackson als unsere JSON-Bibliothek verwenden:


    com.fasterxml.jackson.core
    jackson-databind
    2.9.8

Note that these techniques are not limited to these two libraries. Wir können unseren bevorzugten JPA-Anbieter und unsere JSON-Bibliothek ersetzen.

3. Methoden serialisieren und deserialisieren

Die einfachste Möglichkeit, ein JSON-Objekt in einer relationalen Datenbank beizubehalten, besteht darin,convert the object into a String zu speichern, bevor es beibehalten wird. Dann werden wirconvert it back into an object, wenn wir es aus der Datenbank abrufen.

Wir können dies auf verschiedene Arten tun.

Der erste, den wir uns ansehen werden, ist die Verwendung voncustom serialize and deserialize methods.

Wir beginnen mit einer einfachenCustomer-Entität, in der der Vor- und Nachname des Kunden sowie einige Attribute zu diesem Kunden gespeichert sind.

Ein Standard-JSON-Objekt würde diese Attribute alsHashMapdarstellen. Daher verwenden wir hier Folgendes:

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

Anstatt die Attribute in einer separaten Tabelle zu speichern, gehen wir zustore them as JSON in a column in the Customers table. Dies kann dazu beitragen, die Komplexität des Schemas zu verringern und die Leistung von Abfragen zu verbessern.

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

Wir können diese Methode manuell aufrufen, bevor sie fortbesteht, oder wir können sie von der MethodesetCustomerAttributes aufrufen, sodass bei jeder Aktualisierung der Attribute auch die JSON-Zeichenfolge aktualisiert wird. 

Als nächsteswe’ll create a method to deserialize the JSON string back into a HashMap object, wenn wirCustomer aus der Datenbank abrufen:

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

Es gibt wieder einige verschiedene Stellen, an denen wir diese Methode aufrufen können. In diesem Beispiel wird sie jedoch manuell aufgerufen. 

Das Fortbestehen und Abrufen desCustomer-Objekts würde also ungefähr so ​​aussehen:

@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. Attributkonverter

If we are using JPA 2.1 or higher können wirAttributeConverters verwenden, um diesen Prozess zu optimieren.

Zunächst erstellen wir eine Implementierung vonAttributeConverter. Wir werden unseren Code von früher wiederverwenden:

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

}

Als Nächstes weisen wir Hibernate an, unsere neuenAttributeConverter für das FeldcustomerAttributes zu verwenden. Fertig:

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

With this approach, we no longer have to manually call the serialize and deserialize methods since Hibernate wird das für uns erledigen. Wir können dasCustomer-Objekt einfach normal speichern und abrufen.

5. Fazit

In diesem Artikel haben wir einige Beispiele dafür gesehen, wie JSON-Objekte mit Hibernate und Jackson beibehalten werden.

Unser erstes Beispiel befasste sich mit einer einfachen, kompatiblen Methode mit benutzerdefinierten Serialisierungs- und Deserialisierungsmethoden. Und zweitens haben wirAttributeConverters eingeführt, um unseren Code zu vereinfachen.

Lesen Sie wie immer den Quellcode für dieses Tutorialover on Github.