Оптимизация SQL запросов — Entity для промежуточных таблиц в JPA
При работе со Spring Data JPA и @ManyToMany частой проблемой являются неоптимальные SQL-запросы из-за избыточных JOIN’ов. Создание отдельной Entity для промежуточной таблицы решает эту проблему, позволяя оптимизировать запросы и снизить нагрузку на базу данных. Такой подход также улучшает читаемость и поддержку кода.
Изменение версии java в Ubuntu
Рассматриваемая система — Ubuntu 22.04. Нужно сделать так, чтобы была возможность одной командой изменить дефолтную версию java. На самом деле оно уже есть, и чтобы изменить версию java в ubuntu, нужно лишь использовать команду: Эта команда изменит ссылку файла /usr/bin/java, которая ссылается на одну из установленных версий java (обычно в директории /usr/lib/jvm). Также переменная JAVA_HOME, которая по-умолчанию ссылается на /usr/bin/java, попадёт в выбранную версию. Всё работало до того момента, когда мне понадобилось добавить GraalVm. Во-первых, GraalVm не появляется в списке update-alternatives; Во-вторых, даже если его туда добавить, то например, Intellij Idea при попытке компилляции проекта выдает ошибку: ‘gu’ tool was not found in your JAVA_HOME.This probably means that the JDK at ‘/usr/bin/java’ is not a GraalVM distribution. Проблема с граалем заключается в том, что Idea пытается найти другие бинарные файлы грааля в одной директории с файлом java из $JAVA_HOME, но их ведь нету в /usr/bin. Проблема решается тем, чтобы удалить…
Логгирование JMS сообщений
Различные способы логгирования JMS сообщений: 1. Логгирование внутри конвертора (Плюс в том, что будет логгироваться тело сообщения как есть. Если сообщение невозможно распарстить, то оно тоже залоггируется (если конечно это TextMessage)): 2. Логгирование внутри jmsTemplate при отправке (Тоже тело сообщения как есть): 3. Логгирование внутри @JmsListener’а (Тоже тело сообщения как есть): 4. Установка уровня логгирования для входящих сообщений (Минус в том, что логгируется объект Message целиком, и тело сообщения может просто не влезть в максимальную длину записи лога):
Spring data jdbc: one-to-one, one-to-many relations
Т.к. в Spring Data JDBC нет стандартных хибернейтовских аннотаций типа @OneToOne, @OneToMany и @JoinColumn, то для меня было проблематично понять можно ли там вообще организовать отношения и использовать их при получении или сохранении объектов. Оказалось это делается так: One-To-One При такой реализации объект Operation без проблем вычитывается из БД уже с смапленным внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненным TaxInfo (корректно заполняются поля id и operationId. One-To-Many Несколько проблематично отношение один ко многим. Здесь сложность состояла в том, что я использовал List для агрегации нескольких TaxInfo, и при сохранении получал эксепшн ConstraintViolationException. Решение состояло в том, чтобы использовать Set (или Map): При такой реализации объект Operation без проблем вычитывается из БД уже с смапленными внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненными TaxInfo (корректно заполняются поля id и operationId. Теперь про эксепшены. У меня были проблемы именно с аннотацией @MappedCollection в…
Задержка принятия следующего Jms сообщения после ошибки
Вариант реализации JmsListenerContainerFactory (на основе DefaultJmsListenerContainerFactory) для задержки принятия следующего jms сообщения, если был выброшен необработанный эксепшен: Инициализация выглядит следующим образом
9.Транзакционность в JMS
Транзакционность используется для возвращения сообщения обратно в очередь, в случае возникновения исключения при его обработке. Для настройки транзакционности, нужно указать ContainerFactory бину — бин PlatformTransactionManager. Пример настроек JMS: Для того, чтобы rollback сообщения сработал, достаточно чтобы из метода помеченного @JmsListener выбросилось необработанное исключение. Таким образом, исходное сообщение снова появится в очереди и его хэадер JMSXDeliveryCount увеличится на 1. Но здесь есть сайд-эффект, т.к. это сообщение через секунду снова залетит в приложение. Таким образом, если исключение будет постоянно появляться — мы попадём в бесконечный цикл ( есть способ задержки принятия следующего Jms сообщения после ошибки ). По поводу транзакционности, есть пара статуй от IBM: https://community.ibm.com/community/user/integration/blogs/stephanie-wilkerson1/2021/02/25/understanding-mq-backout-queues-thresholds https://www.ibm.com/docs/en/ibm-mq/9.2?topic=applications-handling-poison-messages-in-mq-classes-jms
Кастомная Jackson десериализация/сериализация
Допустим, имеем такую DTO: А нам нужно десериализовать из такого json: То используем над полем аннотацию @JsonDeserialize(using = ProductDtoDeserializer.class) и делаем десериализатор А теперь сделаем так, чтобы строковое поле сериализовывалось в UpperCase
Проверка json в mockMVC тестах и не только
Протестировать ваш jsonPath можно в сервисе https://jsonpath.com/ Кроме того, просто извлечь значение согласно указанного jsonPath можно так:
Добавление модулей в ObjectMapper
Часто бывают проблемы с десериализацией дат из строки в, например, LocalDateTime. Порой это выглядит так: Есть несколько способов решить эту проблему. Один из них е использование аннотации @JsonFormat над нужным полем в dto Но бывают случаи, когда такое решение не приемлемо. Однако, есть ещё способ — кастомизация самого ObjectMapper’а. Я имею в виду про добавление модулей для сериализации/десериализации. Например, добавление модуля поддержки jsr310: Или добавление модуля поддержки joda: Наряду с этим, есть возможность писать собственные модули для сериализации/десериализации чего угодно. Не отходя от темы дат, приведу пример десериализации даты, представленной в любом из ожидаемых форматов: где классы выглядят так:
