Spring @Transactional не обновляет данные в сеансе - PullRequest
0 голосов
/ 31 марта 2020

У меня очень странная проблема на сервере Spring / Hibernate. Моя коллега, работающая над Ма c, не испытывает такой же проблемы, но я нахожусь на Ubuntu, и происходит что-то странное.

Это, вероятно, относится к этой проблеме , но предложенный исправления не работают для меня.

У меня есть работа, которая получает сообщения от Amazon SQS и выполняет эту работу.

Мне пришлось сделать класс @Transactional, чтобы обойти

org.hibernate.LazyInitializationException: 
could not initialize proxy [co.example.model.Scene#5] 
- no Session 

В конце этой работы некоторые данные сохраняются

        scene.setStatus(4);
        sceneRepository.save(scene);

        log.info("sceneProcessingComplete" +  scene.getId() + " " + scene.getStatus());

Эти данные сохраняются в база данных, как и ожидалось. Однако этот журнал возвращает предыдущее значение.

После этого серверу поступает вызов на сервер от клиента, который также возвращает предыдущее значение, даже если я вижу, что это 4 в БД.

Как будто @Transactional не обновляет сущность в сеансе?

@Service
@Scope("singleton")
@EnableAsync
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Slf4j
public class ProcessVideoQueueJob extends AmazonService {


@Scheduled(fixedRate = 50000)
public void start() {

    this.initSQSClient(); 
    this.initS3Client();
    this.checkProcessingQueue();

} 

public void checkProcessingQueue(){
  ....
complete(processingJob, jobStatusNotification);

public void complete(ProcessingJob processingJob,
JobStatusNotification jobStatusNotification ){
    try{
     Scene scene = sceneRepository.getOne(sceneId);
      ....
      scene.setStatus(4);
        sceneRepository.save(scene);

        log.info("sceneProcessingComplete" +  scene.getId() + " " + scene.getStatus());


        return; 

Добавление этого возврата означало, что первый журнал теперь отображает 4.

Последующий вызов API

@RequestMapping(path = "/scene/{id}", method = GET)
public ResponseEntity<?> getScene(@PathVariable("id") long id)  {
    JwtUser jwtUser = this.getJwtUser();

    Scene scene = sceneService.getScene(id);

    if(!canAccess(jwtUser, scene)){
        return this.getUnauthorizedResponse();
    }

    log.info("Get Scene: " + scene.getId() + "  status:" + scene.getStatus());

    return ResponseEntity.ok(scene);
}

Возвращает 2. В базе данных это 4.

репозиторий Scene. java

public interface SceneRepository extends JpaRepository<Scene, Long> {


    @Transactional
    @Modifying
    @Query(value ="UPDATE example.scene SET video_id = :video_id, status = :status WHERE id = :id",nativeQuery=true)
    void updateSceneVideoId(@Param("id") Long id, @Param("video_id") Long videoId, @Param("status") int status );

    @Transactional
    @Modifying
    @Query(value ="UPDATE example.scene SET image_id = :image_id, status = :status WHERE id = :id",nativeQuery=true)
    void updateSceneImageId(@Param("id") Long id, @Param("image_id") Long imageId, @Param("status") int status );


}

1 Ответ

0 голосов
/ 31 марта 2020

Не могли бы вы попытаться переместить метод start в другой класс, который вызывает метод complete() класса ProcessVideoQueueJob. Например, вы можете создать новый класс ProcessVideoQueueJobStarter Ниже приведен фрагмент кода.

public class ProcessVideoQueueJobStarter extends AmazonService {

    @Autowired
    ProcessVideoQueueJob pj;

    @Scheduled(fixedRate = 50000)
    public void start() {

        this.initSQSClient(); 
        this.initS3Client();
        this.checkProcessingQueue();

    } 

        public void checkProcessingQueue(){
          ....
        pj.complete(processingJob, jobStatusNotification);

    *
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...