Как хранить JSON в базе данных, не привлекая внимания DBA
Рано или поздно перед любым разработчиком встает проблема рассогласования импеданса между объектной и реляционной моделью. Звучит дико, конечно. Скажем проще. Рано или поздно каждому разработчику приходится хранить в базе данных что-то такое, что там хранить неудобно. Например, какой-то сущности надо приписывать какие-то дополнительные атрибуты, названия и типы данных. Или кто-то хочет отобразить на реляционные таблицы дерево наследования. Для этих задач есть известные проработанные и неудобные способы решения, которые к тому же легко могут привести к проблемам с производительностью.
Альтернатива этому всему — хранение таких данных в виде JSON. Но реляционные СУБД JSON не любят. Дошло даже до того, что Mongo, киллер-фичей которой как раз является хранение данных в виде JSON, набрала на этом нешуточную популярность. Но, к счастью, эти времена потихоньку отступают. Во многом благодаря усилиям разработчиков PostgreSQL. Раньше все попытки положить JSON в базу данных встречали враждебную реакцию со стороны DBA, аналитиков и QA. Эту реакцию можно описать так: «У нас же тогда будет не база данных, а помойка!»
Спикеры поговорят о связанных с этим проблемах, расскажут, как их можно решить не выходя из реляционной структуры, и продемонстрируют, что с этими решениями не так. Также вы узнаете, в каких случаях для решения этих проблем можно применить JSON и почему львиная доля опасений DBA, аналитиков и QA теперь неактуальна. А еще — как при использовании JSON не выстрелить себе в ногу, потому что нюансы есть.
- # hibernate
- # jpa
- # json
- # postgresql
- # spring-data
Как хранить файлы в базе PostgreSQL?
Мне надо хранить в PostgreSQL файлы пользователей но я не как не могу найти информацию об этом в документации. Как мне загружать туда файлы? И как мне организовать доступ к ним? По идее каждый пользователь может иметь файлы, соответсвенно должна быть таблица с путями? Правильно? Как такое вообще традиционно решается в случае с PostgreSQL?
Отслеживать
задан 26 апр 2017 в 21:40
5,327 11 11 золотых знаков 58 58 серебряных знаков 117 117 бронзовых знаков
А зачем файлы хранить именно в БД ?
26 апр 2017 в 21:40
@Mike а как правильно? У меня нет такого условия что именно в БД, это показалось мне логичным. А как обычно делают? Я просто в первый раз с работой с БД сталкиваюсь так что простите за глупые вопросы если что.
26 апр 2017 в 21:42
В бд можно хранить например пути к файлам, а сами файлы просто на диске, так обычно проще. И одного совершенно правильного пути нет. тут уже могут быть нюансы
26 апр 2017 в 21:46
@Mike В бд можно хранить например пути к файлам, а сами файлы просто на диске обычно так делают?
26 апр 2017 в 21:47
ну зависит от того, что потом с ними происходит. Если у вас например web-приложение и файлы надо давать на скачку, то nginx файл пользователю гораздо быстрее и с меньшими накладными расходами отдаст, чем скрипт который будет тащить данные из БД и отдавать пользователю
26 апр 2017 в 21:50
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Вы не можете найти информацию в документации о том, как хранить файлы в базе данных, потому что это неправильно.
Хранить можно, но зачем?
СУБД лишь абстракция над набором файлов (таблиц, индексов и т.д) Вы делаете запрос к таблице, СУБД перемещает указатель в каком-то файле, ставит какие-то блокировки, чтобы выбрать определенную запись, пишет это все в кеш..И теперь становится понятно, что база данных — это лишняя прослойка для доступа к файлам.
Файлы — при использовании по прямому назначению (отдать данные клиенту) всегда быстрее, чем хранение в базе данных, потому что требуется меньше процедур, чтобы их прочитать.
Если вы храните файлы в базе данных, вы забивайте кеш, который должен использоваться для других запросов. Со временем, база данных разрастается, процессы которые отдают файлы забивают свободный пул, возрастает нагрузка и используемое место, вам требуется уже шардинг и другие ненужные процедуры.
Для реализации файлового хранилища, храните адрес сервера (если их несколько) и полный путь к файлу на сервере в таблице и отдавайте файлы через nginx.
P.S Иногда есть логическое обоснование хранения файлов в БД, но к сожалению, это маленький процент общих вариантов.
Разработка распределенной очереди с отложенными задачами на основе PostgreSQL
Максим покажет процесс создания очереди задач на основе реляционной БД. Она поддерживает ретраи и выполнение задач в строгой последовательности по одной сущности. В слайдах будет показан код на Java и SQL: структура таблиц и строчек. Сам метод основан на блокировках Postgres и ожидании блокировки внутри транзакции, пока задача выполняется. Спикер также расскажет про статистику, про то, сколько весит очередь, ее индексы и про то, откуда вообще взяты эти данные (немного обучения диагностике в Postgres). А в конце — еще и результаты нагрузки.
- # databases
- # postgresql
- # queues
Спикеры

Максим Иванов
Компания: Тинькофф
Приглашенные эксперты

Илья Сазонов
Компания: Всегда.Да
Ведущие

Алексей Стукалов
Компания: Haulmont
Другие доклады по теме «Spring and Database»
Смотреть запись
Тип доклада: Доклад
Как хранить JSON в базе данных, не привлекая внимания DBA

Илья Сазонов
Компания: Всегда.Да

Федор Сазонов
Компания: Сбер
- Доклад на русском языке RU
- Сложность доклада —
Смотреть запись
Тип доклада: Обсуждение
Блеск и нищета Hibernate

Андрей Беляев
Компания: HAULMONT

Андрей Аркаев
Компания: Naumen

Алексей Стукалов
Компания: Haulmont

Антон Черноусов
Компания: Yandex Cloud
- Доклад на русском языке RU
Смотреть запись
Тип доклада: Доклад
Spring Boot с Amazon Web Services SDK: взаимодействие основных сервисов

Август Вилакия
Компания: Альфа-Банк
- Доклад на русском языке RU
- Сложность доклада —
Смотреть запись
Тип доклада: Доклад
Урок географии для Java-разработчиков. География и Java в одном чайнике

Павел Кислов
Компания: Домклик
- Доклад на русском языке RU
- Сложность доклада —
Смотреть запись
Тип доклада: Доклад
Hibernate 6: что нового и почему это важно

Андрей Беляев
Компания: HAULMONT
- Доклад на русском языке RU
- Сложность доклада —
Конференция для опытных Java-разработчиков
Мы в социальных сетях
- Телефон: +7 (812) 313-27-23
- E-mail: support@jokerconf.com
- Телеграм: @JUGConfSupport_bot
Загрузка файла из контроллеров Spring
Существует типичная задача, когда нужно сгенерировать PDF-файл на сервере и предоставить его для скачивания пользователю. Например, это может быть отчет, который формируется на основе данных из базы данных, и пользователь должен иметь возможность скачать его в виде PDF-файла.
Идеально для решения этой задачи подходит сочетание двух технологий: шаблонизатора freemarker для формирования HTML-шаблона отчета и библиотеки iText для преобразования HTML в PDF. Однако возникает вопрос — как организовать загрузку этого файла через Spring контроллер?
Генерация PDF
Для начала требуется сгенерировать сам PDF. В качестве шаблона используется HTML, который заполняется данными при помощи freemarker. Затем этот HTML преобразуется в PDF с помощью iText.
String html = freemarkerTemplateEngine.process("reportTemplate", model); ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream(); PdfRendererBuilder builder = new PdfRendererBuilder(); builder.withHtmlContent(html, "/"); builder.toStream(pdfOutputStream); builder.run();
Метод freemarkerTemplateEngine.process заполняет HTML-шаблон данными, а PdfRendererBuilder преобразует HTML в PDF.
Отправка файла через Spring контроллер
Теперь, когда PDF сгенерирован, его можно отправить пользователю. Для этого в контроллере Spring создается новый метод, который возвращает ResponseEntity.
@RequestMapping(value = "/download", method = RequestMethod.GET) public ResponseEntity<byte[]> downloadReport() < byte[] pdfData = generatePdfReport(); // метод, который генерирует PDF HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_PDF); headers.setContentDispositionFormData("filename", "report.pdf"); return new ResponseEntity<>(pdfData, headers, HttpStatus.OK); >
В этом методе генерируется PDF, затем создается новый объект HttpHeaders, в котором устанавливается тип контента и имя файла. Затем создается и возвращается новый объект ResponseEntity, который содержит данные PDF, заголовки и статус HTTP.
Таким образом, при запросе к данному контроллеру пользователь получает PDF-файл, который можно скачать.
Это один из возможных способов решения задачи. Важно помнить, что в разных ситуациях могут потребоваться разные подходы.