Проблема с merge() в спрингдатных репозиториях в абсолютно идиотском решении сделать репозиторий по умолчанию транзакционным. Репозиторий - это только доступ к данным, управление транзакциями - это уже инфраструктурный уровень, и заниматься этим должны соответствующие фасады.
Причём можно же было сделать по-нормальному, раз уж так хотелось обмазаться аннотациями, и указать @Transactional(propagation = MANDATORY). При таком подходе merge() из save() можно было бы невозбранно выбросить и ничего не поменялось. Но в угоду красивым презентациям сделали как сделали. В результате получаем выходы сущностей за границы транзакций со всеми вытекающими.
Правильный вариант:
И тут мы плавно подходим к тому, что декларируемая (ничего общего с реальностью не имеющая, конечно) взаимозаменяемость разных spring-data-XXX идёт лесом, т.к. решили мы заменить JPA на jdbc, и вот уже наше обновление сломалось, просто потому, что save-то никто и не сделал.
Если внимательно посмотреть на возвращаемый методом результат и немного подумать, то можно увидеть, что метод возвращает CompletableFuture, следовательно, метод - асинхронный. То, что в каких-то граничных случаях он ведёт себя синхронно, не означает, что с ним можно так работать.
По выходу из этого метода, вообще не факт, что событие отправлено, т.ч. маркировать сущность как отправленную и сохранять её в БД - преждевременно.
outboxRepository.save(record);
Зачем? Чтобы просто погонять лишние запросы в БД? Ты же только что эти записи из БД получил, при комите транзакции JPA сам разберётся, что надо флашить, а что нет.
Так тебе? Или таки твоему работодателю, а ты просто исполняешь работы по замене? Если второе, то бюррократия работает в обе стороны, написал бумажку и жди. Жопа бумажкой прикрыта.
Тратить свои деньги не на себя - заведомо провальная стратегия.
Да это либо жирный тролль, либо сказочный д…б, работающий в одно лицо над одним древнючим проектом, в котором, кроме как, условно, поменять надпись на кнопке, ничего делать не нужно.
На заре моей карьеры даже матёрые фокспрошники, по нескольку раз в день зипающие весь проект в архив, узнав про актуальный тогда svn сразу признали, что это куда лучше, чем мегабайты кода, которые перелопатить при возникновении НЁХ не представляется возможным. Особенно, когда реально надо точечно откатить изменения, а не до конкретной версии.
Раз уж коснулись webjar-ов надо идти до конца: разбить проект на, условно, 2 модуля (фронт и бэк). Фронт тем же грэдлом/мавеном собирать в webjar, и уже его цеплять в качестве зависимости к бэку.
При необходимости, фронт лёгким движением руки переезжает в отдельный самостоятельный проект, а для бэка почти ничего не меняется.
В Китае ситуация обратная: пин должен быть не менее 5 символов, и соотечественники, не зная данной особенности и имея 4-х значный пин, блокировали себе карты, т.к. банкоматы тупо считают невалидным пин с количеством знаков менее 5.
А вот для правильного ввода 0 нужно вводить последним, а не первым символом.
А что изменится, если для запуска в параллель вместо spring-а будут простые Runnable/Callable в ExecutorService? А ничего не изменится, т.к. вся магия делается внутри хибернета.
Единственное место, где почему-то предпочтение отдано spring-у - это PaymentDocumentSaver. Хотя туда прокидывается SessionFactory и, значит, ничто не мешало раз уж так хотелось нативных запросов использовать Session#createNativeQuery().
А вообще, конечно, странно это - использовать хибер и не использовать типобезопасный Criteria API. Особенно, учитывая то, что ничего базоспецифичного в запросах не делается. А просто обновление одного поля сущности.
Неуважаемые, вы бы прежде, чем брать денежку за сертификацию, попросили знающих людей поревьюить ваши вопросы. Это же полная кринжатина.
Код некомпилируемый. Где правильный вариант?
Гениальный вопрос, где все варианты, в принципе, могут быть верными и, не зная контекста используемых библиотек, правилльные ответы можно только угадать.
Но вот то, что оно не умеет в null - довольно печально, а LazyConstant<Optional<Something>> выглядит отвратительно, и пользоваться этим будет неудобно.
Чтобы не задаваться подобными вопросами, например.
Проблема с
merge()в спрингдатных репозиториях в абсолютно идиотском решении сделать репозиторий по умолчанию транзакционным. Репозиторий - это только доступ к данным, управление транзакциями - это уже инфраструктурный уровень, и заниматься этим должны соответствующие фасады.Причём можно же было сделать по-нормальному, раз уж так хотелось обмазаться аннотациями, и указать
@Transactional(propagation = MANDATORY). При таком подходеmerge()изsave()можно было бы невозбранно выбросить и ничего не поменялось. Но в угоду красивым презентациям сделали как сделали. В результате получаем выходы сущностей за границы транзакций со всеми вытекающими.И тут мы плавно подходим к тому, что декларируемая (ничего общего с реальностью не имеющая, конечно) взаимозаменяемость разных
spring-data-XXXидёт лесом, т.к. решили мы заменить JPA на jdbc, и вот уже наше обновление сломалось, просто потому, что save-то никто и не сделал.потому что сам и ответил.
Если внимательно посмотреть на возвращаемый методом результат и немного подумать, то можно увидеть, что метод возвращает
CompletableFuture, следовательно, метод - асинхронный. То, что в каких-то граничных случаях он ведёт себя синхронно, не означает, что с ним можно так работать.По выходу из этого метода, вообще не факт, что событие отправлено, т.ч. маркировать сущность как отправленную и сохранять её в БД - преждевременно.
Зачем? Чтобы просто погонять лишние запросы в БД? Ты же только что эти записи из БД получил, при комите транзакции JPA сам разберётся, что надо флашить, а что нет.
В svn можно было поставить lock на файл. А самое сложное, когда закончил работать, не забыть снять.
Сразу видно человека, который не знает, что программист не решает аппаратные проблемы.
Такой файлообменник сгубили…
Так тебе? Или таки твоему работодателю, а ты просто исполняешь работы по замене? Если второе, то бюррократия работает в обе стороны, написал бумажку и жди. Жопа бумажкой прикрыта.
Тратить свои деньги не на себя - заведомо провальная стратегия.
Да это либо жирный тролль, либо сказочный д…б, работающий в одно лицо над одним древнючим проектом, в котором, кроме как, условно, поменять надпись на кнопке, ничего делать не нужно.
На заре моей карьеры даже матёрые фокспрошники, по нескольку раз в день зипающие весь проект в архив, узнав про актуальный тогда svn сразу признали, что это куда лучше, чем мегабайты кода, которые перелопатить при возникновении НЁХ не представляется возможным. Особенно, когда реально надо точечно откатить изменения, а не до конкретной версии.
Или доктор Уотсон.
Так а потыкать-то где?
Раз уж коснулись webjar-ов надо идти до конца: разбить проект на, условно, 2 модуля (фронт и бэк). Фронт тем же грэдлом/мавеном собирать в webjar, и уже его цеплять в качестве зависимости к бэку.
При необходимости, фронт лёгким движением руки переезжает в отдельный самостоятельный проект, а для бэка почти ничего не меняется.
В Китае ситуация обратная: пин должен быть не менее 5 символов, и соотечественники, не зная данной особенности и имея 4-х значный пин, блокировали себе карты, т.к. банкоматы тупо считают невалидным пин с количеством знаков менее 5.
А вот для правильного ввода 0 нужно вводить последним, а не первым символом.
Два моих и один паспорт супруги прямо таки всухую опровергают этот тезис: ни разу код региона выдачи не совпал с первыми двумя цифрами серии.
А что изменится, если для запуска в параллель вместо spring-а будут простые
Runnable/CallableвExecutorService? А ничего не изменится, т.к. вся магия делается внутри хибернета.Единственное место, где почему-то предпочтение отдано spring-у - это
PaymentDocumentSaver. Хотя туда прокидываетсяSessionFactoryи, значит, ничто не мешало раз уж так хотелось нативных запросов использоватьSession#createNativeQuery().А вообще, конечно, странно это - использовать хибер и не использовать типобезопасный Criteria API. Особенно, учитывая то, что ничего базоспецифичного в запросах не делается. А просто обновление одного поля сущности.
TL/DR. Распараллеливаем процесс вставки данных в PostgreSQL при помощи
SpringJPA/Hibernate с сохранением атомарности всей операцииHibernate
JPA
Неуважаемые, вы бы прежде, чем брать денежку за сертификацию, попросили знающих людей поревьюить ваши вопросы. Это же полная кринжатина.
Код некомпилируемый. Где правильный вариант?
Гениальный вопрос, где все варианты, в принципе, могут быть верными и, не зная контекста используемых библиотек, правилльные ответы можно только угадать.
И это уровень "Профессионал"...
Коллеги, обходите эту шарашку стороной.
Но вот то, что оно не умеет в
null- довольно печально, аLazyConstant<Optional<Something>>выглядит отвратительно, и пользоваться этим будет неудобно.Это ровно до тех пор, пока их "из гнезда" не выпнут.
А есть какой-то другой незаброшенный grizzly?