Зачастую бизнес‑объекты в информационных системах хранятся в классических реляционных базах данных, где каждому атрибуту объекта соответствует колонка в таблице.
Чтобы изменить такую объектную модель, например, добавить или удалить атрибут, нужно внести изменения в схему базы данных, то есть выполнить DDL‑операцию. Она сопровождается блокировками таблиц и увеличением времени простоя при работе с данными. Кроме того, при увеличении числа атрибутов можно превысить ограничение на количество колонок в таблице. Например, в Postgres их можно создать не более 1600.
Эти проблемы можно устранить, используя хранение данных в формате JSON. Основные преимущества такого подхода:
Обращение к динамическим полям может осложниться при работе с Hibernate до версии 6.2. Более ранние версии не позволяют обращаться к полям внутри JSON на уровне HQL, что ограничивает возможности фильтрации и сортировки. Поэтому оптимальный вариант — использовать Native SQL. Hibernate позволяет регистрировать SQL‑функции, чтобы вызывать их из HQL‑запросов. Пример регистрации такой функции для Postgres приведен ниже:
registerFunction("jsonQuery",
new SQLFunctionTemplate(StandardBasicTypes.STRING,
"jsonb_path_query_first(?1, ?2)::varchar"));
Первый параметр — колонка в БД, внутри которой хранится JSON, выполняющий запрос.
Второй параметр — запрос в виде JSON Path, который позволяет добраться до определенных полей.
Пример структуры JSON и использования на ней SQL-функции в запросе:
{
"CPU_Brand": "Intel",
"CPU_Model": "Xeon 8380",
"RAM_Size_GB": 64
}
SELECT obj.id
FROM userObject obj
WHERE jsonQuery(obj.json, '$.CPU_Brand') = 'Intel'
При работе с более сложными вещами, например, фильтрация объектов с вложенными данными, SQL Server требует применения конструкций CROSS APPLY и openjson.