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

Используйте динамическое обновление гибернации для свойств JSON

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

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

Вступление

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

Поскольку Hibernate ORM не поддерживает типы столбцов JSON, мы собираемся использовать библиотеку Hibernate Types , которая предоставляет JsonType , позволяющий сопоставлять Строку , Карту , Список , JsonNode , записи Java или POJOs в столбцах JSON, независимо от того, используете ли вы PostgreSQL, MySQL, Oracle, SQL Server или H2.

Модель предметной области

Наше приложение требует сохранения Книги сущностей, которые выглядят следующим образом:

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(typeClass = JsonType.class, name = "json")
public class Book {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String isbn;

    private String title;

    private String author;

    @Column(columnDefinition = "jsonb")
    @Type(type = "json")
    private String properties;
}

Атрибут свойства сущности отображается в столбце jsonb PostgreSQL, и по этой причине для обработки сопоставления используется тип Json из проекта “Типы гибернации”.

Обновление объекта гибернации без динамического обновления

По умолчанию при изменении сущности:

entityManager
    .unwrap(Session.class)
    .bySimpleNaturalId(Book.class)
    .load("978-9730228236")
    .setTitle(
        "High-Performance Java Persistence, 2nd edition"
    );

Hibernate выполняет инструкцию UPDATE, которая включает в себя все атрибуты сущности, даже те, которые не были изменены:

UPDATE 
    book 
SET 
    author = 'Vlad Mihalcea', 
    properties = '{
        "price":44.99,
        "reviews":[{
                "date":"2017-11-14",
                "rating":5,
                "review":"Excellent book to understand Java Persistence",
                "reviewer":"Cristiano"
            },{
                "date":"2019-01-27",
                "rating":5,
                "review":"The best JPA ORM book out there",
                "reviewer":"T.W"
            },{
                "date":"2016-12-24",
                "rating":4,
                "review":"The most informative book",
                "reviewer":"Shaikh"
            }
        }', 
    title = 'High-Performance Java Persistence, 2nd edition' 
WHERE 
    id = 1

Обратите внимание, что объект properties JSON также задан, и чем больше объект JSON, тем выше влияние на производительность отправки ненужных данных.

Используйте динамическое обновление гибернации для свойств JSON

Как я объяснил в этой статье , вы можете использовать аннотацию @DynamicUpdate , чтобы указать Hibernate, что вы хотите, чтобы оператор UPDATE создавался динамически при очистке контекста сохранения.

Итак, при добавлении @DynamicUpdate аннотации к Книге сущности:

@Entity(name = "Book")
@Table(name = "book")
@TypeDef(typeClass = JsonType.class, name = "json")
@DynamicUpdate
public class Book {
    ...
}

И, повторно запустив предыдущий тестовый случай изменения сущности, мы видим, что Hibernate выполняет инструкцию UPDATE, которая включает только те столбцы, которые были изменены:

UPDATE 
    book 
SET 
    title = 'High-Performance Java Persistence, 2nd edition' 
WHERE 
    id = 1

Намного лучше!

Вывод

Как вы можете видеть, использование функции динамического обновления Hibernate для сущностей, содержащих свойства JSON, является очень хорошей идеей, поскольку она позволяет избежать отправки объектов JSON в базу данных и установить в столбце то же значение, которое было прочитано ранее.

Для получения более подробной информации о сопоставлении столбцов JSON с JPA и Hibernate также ознакомьтесь с этой статьей.