Spring-在应用程序关闭前执行查询(测试)

Spring-在应用程序关闭前执行查询(测试),spring,spring-boot,spring-data-jpa,shutdown-hook,application-shutdown,Spring,Spring Boot,Spring Data Jpa,Shutdown Hook,Application Shutdown,我使用Sprind数据JPA/Hibernate作为持久层运行springboot2.1。在应用程序关闭之前,我在测试中遇到了成功运行查询的问题 详情: 在应用程序上下文启动期间,我通过JPA执行一个查询,假设此查询转换为以下SQL插入mytable'mycolumn'值'abc' 现在我需要在应用程序关闭之前执行另一个查询。例如,这将是updatemytable set mycolumn='xyz',其中mycolumn='abc' 我通过在配置类上使用@PreDestroy来执行查询 @Co

我使用Sprind数据JPA/Hibernate作为持久层运行springboot2.1。在应用程序关闭之前,我在测试中遇到了成功运行查询的问题

详情:

在应用程序上下文启动期间,我通过JPA执行一个查询,假设此查询转换为以下SQL插入mytable'mycolumn'值'abc'

现在我需要在应用程序关闭之前执行另一个查询。例如,这将是updatemytable set mycolumn='xyz',其中mycolumn='abc'

我通过在配置类上使用@PreDestroy来执行查询

@Configuration
MyConfig {

   @Autowired
   private MyTransactionalService myService;

   @PreDestroy
   public void doQuery() {
      mySerivce.runMyQuery(); 

  }
}
mySerivce.runMyQuery delagates到myRepository,myRepository是Spring数据JPA存储库,用于调用更新查询:

MyRepository extends JpaRepository(String, Something) {

   @Modifying
   @Query("UPDATE myEntity e SET e.myColumn = 'xyz' WHERE e.myColumn = 'abc")' 
   void runMyQuery();
}
用@PreDestroy注释的方法执行,但当查询由运行在我的spring测试中的H2 inmemory db执行时,它抛出异常,表示表不存在

问题是,这个表以前肯定存在,因为我能够在应用程序启动期间在该表上执行INSERT。请参阅本文开头部分

我猜shudtown进程正在进行中,因此内存中的数据库被清除了。。。因此没有桌子

在数据库连接仍然正常且应用程序上下文关闭时尚未删除表的情况下,是否仍然可以确保执行查询

@Predestroy的工作原理与预期一致,只需在应用程序类中的某个方法上添加@Predestroy注释即可。我在这里创建了一个示例。为了快速测试,我使用sql文件来初始化我的数据库,正如所描述的,您也可以为它使用服务。当我关闭应用程序时,数据库会根据需要进行更新。请尝试:

中的依赖项:pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zpavel</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>2.4.3</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
            <version>1.4.199</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>
</project>
存储库:

public interface FooRepository extends JpaRepository<Foo, Long> {
}
src/main/resources/data.sql:

INSERT INTO foo (bar) VALUES ('baz');
src/main/resources/application.properties:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
spring.datasource.url=jdbc:mariadb://localhost:3306/test?useSSL=false
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.initialization-mode=always
Application.java

@SpringBootApplication
public class Application {  
    @Autowired
    private FooRepository fooRepository;

    // keep main method here

    @PreDestroy
    private void shutdown() {
        fooRepository.deleteAll();
    }
}

我通过使用DB_CLOSE_ON_EXIT=FALSE克服了这个问题;初始参数

String url = "jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE";

在这种情况下,H2不会终止数据库,并在关闭过程中保持数据库可用。

为什么需要在数据库销毁之前更新表?在测试中,这是销毁的。实时系统中的数据库将是持久的。我真的需要为真正的数据库SQL server。。。但是我希望能够在tests中的mem db中测试这种行为。请在应用程序类中的某个方法上发布带有@PreDestroy注释的代码片段。您粘贴了很多代码,但没有粘贴回答问题的代码。谢谢,好的。忘了吧。我会完成我的答案。它对你有用吗?我把应用程序类的代码放在你的例子中,不使用imem数据库,而是使用MariaDb。有了持久数据库,就没有问题了。另一件事是,在我的例子中,由于模块依赖关系的组织方式,在应用程序类中注入FooService是不可能的,即应用程序看不到FooRepository
@SpringBootApplication
public class Application {  
    @Autowired
    private FooRepository fooRepository;

    // keep main method here

    @PreDestroy
    private void shutdown() {
        fooRepository.deleteAll();
    }
}
String url = "jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE";