Обновление запроса репозитория Spring JPA застряло/блокируется

На всю жизнь я не могу понять, что не так с кодом, из-за которого запрос на обновление зависает. Я проверил запрос непосредственно в базе данных, и все в порядке.

Я могу подтвердить, что приложение может подключиться к базе данных. Приложение может запуститься нормально. Я могу выполнить запрос findBy просто отлично. Это просто запрос на обновление, который застрял.

Класс репозитория:

@Repository
public interface TestRepository extends CrudRepository<Test, String> {
    // Tried with @Modifying(flushAutomatically = true, clearAutomatically = true).  Still no luck.
    @Modifying
    @Query("UPDATE Test SET stopAllPayment = 'Y' WHERE location = 'london'")
    int stopAllPayment();
}

Класс обслуживания

@Service
@RequiredArgsConstructor
public class StopPaymentService {
    private final TestRepository testRepository;

    @Transactional
    public void run() {

        // Stuck here.  Blocking.
        // In debug mode, the thread is waiting at SocketDispatcher.read0()
        testRepository.stopAllPayments();  
    }
}

Основной класс

@SpringBootApplication
@RequiredArgsConstructor
@EnableTransactionManagement
public class Main implements CommandLineRunner {
    private final StopPaymentService service;

    @Override
    public void run(String... args) throws Exception {
        service.run();
    }

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

приложение.yml

spring:
  datasource:
    url: jdbc:oracle:thin:@dbdev:1521/LT110
    username: user
    password: password
    driver-class-name: oracle.jdbc.OracleDriver
  jpa:
    hibernate:
      ddl-auto: none

пом.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath />
    </parent>

   
    <properties>
        <java.version>1.8</java.version>
    </properties>


    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>

        <!-- Oracle JDBC driver -->
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>21.1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.4.5</version>
        </dependency>
    </dependencies>
</project>


person His    schedule 15.05.2021    source источник
comment
кажется, что ваше приложение не может подключиться к базе данных. Убедитесь, что свойства подключения к базе данных указаны правильно. Пожалуйста, предоставьте application.properties и pom.xml. Непонятно, какую базу данных вы используете.   -  person Mykhailo Skliar    schedule 15.05.2021
comment
@MykhailoSkliar, я добавил приложение yml и pom.xml. Приложение может нормально выполнить поисковый запрос. Проблема заключается в запросе на обновление.   -  person His    schedule 15.05.2021
comment
проверить наличие блокировок в базе данных.   -  person Jens Schauder    schedule 15.05.2021
comment
вы должны включить это свойство, чтобы увидеть, какой запрос выполняется, что вызывает вашу проблему с зависанием spring.jpa.show-sql=true   -  person user3696953    schedule 15.05.2021
comment
Проверьте эту ссылку, я думаю, это вам поможет!   -  person AnilkumarReddy    schedule 15.05.2021
comment
@JensSchauder, уже проверил. Ничто не блокирует базу данных. У меня есть приложение nodejs, выполняющее тот же запрос на обновление. Это как-то связано с весенним загрузочным приложением.   -  person His    schedule 15.05.2021
comment
В соответствии с проблемой причина будет заключаться в том, что приложение выполняет оператор SQL (запрос или обновление) для Oracle db и ожидает ответа от сервера базы данных. По умолчанию поток будет продолжать ждать бесконечно долго, пока не получит ответ. Это означает, что поток может зависнуть в этом состоянии на очень долгое время, если оператор SQL очень сложный и его выполнение занимает много времени, если база данных работает очень медленно, если сервер базы данных перестает отвечать на запросы или если проблема в сетевом соединении между сервером приложений и БД.   -  person AnilkumarReddy    schedule 15.05.2021
comment
@AnilkumarReddy, в моем запросе нет ничего сложного. Посмотри. Это простой запрос на обновление. Тот факт, что мое приложение nodejs может его выполнить, говорит мне, что мне что-то не хватает в моем весеннем загрузочном приложении.   -  person His    schedule 15.05.2021
comment
Где именно вы вызываете метод StopPaymentService.run()? Я не вижу никакого кода в вашем примере. SpringApplication.run() не имеет ничего общего с StopPaymentService.run()   -  person Mykhailo Skliar    schedule 15.05.2021
comment
@MykhailoSkliar, обновил вопрос. Это в Main.java.   -  person His    schedule 15.05.2021
comment
@ Его Да, теперь я это вижу. Но у вас все еще есть проблема? Если это так, все равно проверьте мой ответ, возможно, вам нужно расширить SpringBootServletInitializer, как в моем примере.   -  person Mykhailo Skliar    schedule 15.05.2021
comment
Если он не ждет базу данных, он ждет чего-то еще. Используйте отладчик, чтобы найти точное местоположение кода и трассировку стека, где он ожидает. Посмотрите на потоки, чтобы увидеть, что он ждет.   -  person Jens Schauder    schedule 16.05.2021
comment
@JensSchauder Для меня это также похоже на проблему с потоками. Например, если диспетчер транзакций находится в одном потоке, а средство запуска командной строки — в другом, то они могут блокировать друг друга или работать некорректно. Вот почему я предлагаю расширить SpringBootServletInitializer (см. мой ответ). Это может решить проблему с потоками.   -  person Mykhailo Skliar    schedule 16.05.2021
comment
@MykhailoSkliar, вы должны уточнить это в своем ответе, потому что сейчас я понятия не имею, почему вы думаете, что ваш ответ помогает.   -  person Jens Schauder    schedule 16.05.2021
comment
@ Йенс Шаудер, оказалось, ты прав. Это проблема блокировки базы данных. Вы хотите добавить это как свой ответ, чтобы я одобрил?   -  person His    schedule 24.05.2021


Ответы (2)


Когда метод find работает и зависает только обновление, наиболее вероятное объяснение - блокировка базы данных.

Запустите обновление, а затем проверьте базу данных на блокирующие блокировки. Подробности того, как это сделать, зависят от базы данных.

person Jens Schauder    schedule 24.05.2021

Согласно этой статье: https://howtodoinjava.com/spring-boot/command-line-runner-interface-example/

правильный код для весеннего загрузочного приложения, реализующего CommandLineRunner, следующий:

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer implements CommandLineRunner {

    @Autowired
    private StopPaymentService stopPaymentService;
 
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SpringBootWebApplication.class);
    }
 
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }
 
 
    @Override
    public void run(String... args) throws Exception {
        stopPaymentService.run();
        logger.info("Application Started !!");
    }
}
person Mykhailo Skliar    schedule 15.05.2021