Spring Data JpaRepository saveAndFlu sh в @Transactional не работает - PullRequest
0 голосов
/ 26 марта 2020

В настоящее время я сталкиваюсь с проблемой Spring-Data / Hibernate, которую я кратко расскажу.

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

    @Async
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void process(Long reportId, SearchCriteria searchCriteriaTo) {

        ReportEntity report = reportRepository.findById(reportId).get();
        report.setStatus(ReportGenerationStatus.START);
        reportRepository.saveAndFlush(report);

        Stream<RawDataEntity> rawDataEntityStream = this.rawDataRepository
            .findAllFiltered(...);

        report.setStatus(ReportGenerationStatus.GENERATING_REPORT);
        report.setProgress(50);
        reportRepository.saveAndFlush(report);

        ...

        rawDataEntityStream.forEach(() -> DoSomething())

        ...

        report.setStatus(ReportGenerationStatus.FINISHED);
        report.setProgress(100);
    }

Моя проблема в том, что, насколько я понимаю, saveAndFlu sh должно записать промежуточные шаги объекта ReportEntity в базу данных, но это не так. Я использую базу данных Posgres и проверил это с помощью PGAdmin, а также написал клиент опроса, который постоянно извлекает ReportEntity.

    @Transactional(readOnly = true)
    public ReportEto getReportByKey(UUID key) {
        // entityManager.clear();
        ReportEntity reportEntity = this.reportRepository.findByKey(key);
        return getBeanMapper().map(reportEntity, ReportEto.class);
    }

Но статус «GENERATING_REPORT» не записывается в БД. Только после окончательной фиксации статус обновляется до FINSIH. Я попытался установить уровень изоляции «READ_UNCOMMITTED», но это также не имеет эффекта. Журналы отладки Hibernate, однако, предполагают, что обновление инициировано:

o.h.e.i.DefaultMergeEventListener        : EntityCopyObserver strategy: disallow
o.h.e.i.AbstractFlushingEventListener    : Processing flush-time cascades
o.h.e.i.AbstractFlushingEventListener    : Dirty checking collections
o.h.e.i.AbstractFlushingEventListener    : Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects
o.h.e.i.AbstractFlushingEventListener    : Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
o.hibernate.internal.util.EntityPrinter  : Listing entities:
o.hibernate.internal.util.EntityPrinter  : com.capgemini.cusmesonlinereporting.reportmanagement.dataaccess.api.ReportEntity{downloadLink=null, externalUserId=MMUSTER, modificationCounter=0, creationTimestamp=2020-03-26T07:21:03.421700Z, name=2018-1-1_2020-3-23, progress=0, id=1000019, key=ecb0955f-b838-4f30-ac1f-dc94763ac810, status=GENERATING_REPORT}
org.hibernate.SQL                        : update Report set modificationCounter=?, creationTimestamp=?, downloadLink=?, externalUserId=?, key=?, name=?, progress=?, status=? where id=? and modificationCounter=?
Hibernate: update Report set modificationCounter=?, creationTimestamp=?, downloadLink=?, externalUserId=?, key=?, name=?, progress=?, status=? where id=? and modificationCounter=?

Я мог бы go вперед и сделать все обновления для ReportEntity во вложенной транзакции с транзакцией REQUIRE_NEW, но я не Я хочу столкнуться с потенциальными DeadLocks из-за длительной транзакции, которая может выполняться несколько раз параллельно. Итак, мои вопросы:

  1. Почему saveAndFlu sh не работает в этом случае?
  2. Существуют ли обходные пути, не связанные с созданием вложенных транзакций?
...