[spring-projects/spring-boot]2.3.7 data.sql不再执行

2024-05-09 314 views
0

从2.3.6升级后。至 2.3.7。开始测试运行时不再执行 data.sql 脚本。

脚本位于src/test/resources

我已经检查过这一点,因为我需要将数据加载到我自己的属性中,所以我用

public class ApplicationInitDocumat implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private MyDBController consistentChecker;
    /**
     * Listen to startup/context refresh events
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // failed to load data  from database which is loaded via data.sql

回答

7

src/test/resources这些脚本是从类路径加载的,因此如果它们位于类路径中,或者src/main/resources只要这些位置中的资源已通过您用来运行测试的任何内容放置在类路径上,则应该没有什么区别。

我们有大量的集成和冒烟测试,这些测试依赖于正在执行的文件,schema.sql并且data.sql它们都通过了,所以我不清楚是什么导致了您的问题。如果您希望我们花更多时间进行调查,请花一些时间提供重现问题的完整但最小的示例。您可以通过将其推送到 GitHub 上的单独存储库或将其压缩并附加到此问题来与我们共享。

4

我尝试通过一个简单的项目重现该问题,但没有成功。我更深入地挖掘并打开了我们实际项目的日志级别。我将日志附加到问题中。看起来data.sql已被执行,但它们没有从数据库中获取。已插入并可查找的数据:

备注:日志直至执行 JPARepostiory.findAll() 为止。随后立即设置断点并结束日志。在 2.3.6 中,findAll()返回了 8 个项目的列表,而 2.3.7 版本则返回了 0 个项目。因此我得出的结论是data.sql没有被执行。但也许结论太快了,根本原因在其他地方。

5

感谢您的日志。不幸的是,它们中没有任何东西可以立即明显地解释不同行为的原因。我不确定您启用了哪些日志记录,但输出似乎不包含任何 Spring 框架或 Spring Boot 代码。例如,我希望看到日志记录org.springframework.jdbc.datasource.init.ScriptUtils,但在这两个文件中都没有看到任何日志记录。您能否更改日志记录配置以包括org.springframework.jdbc确认文件是否正在被处理?

我尝试用一​​个简单的项目重现该问题,但没有成功

这表明问题在某种程度上特定于您的环境或主应用程序的依赖项。前者会让我们很难诊断问题。后者也将在没有我们可以重现问题的样本的情况下出现。

6

抱歉,我不知道应该启用什么样的选项。我已经做了

logging:
  level:
    root: DEBUG

由于它们还不够,请建议设置哪一个。

0

这也是一件奇怪的事。根级调试日志记录应该已经足够了。我怀疑您可能在其他地方有一些配置,这些配置会覆盖除 Hibernate 和少数其他记录器之外的所有记录器的配置。不幸的是,如果不了解有关您的应用程序及其配置的更多信息,我无法判断是否确实如此。我认为我们已经达到了需要一个能够重现问题的样本才能取得一些进展的地步。

1

日志记录的配置很奇怪。根级别不适用于子级别 - 不知道这是否是另一个问题?无论如何,这样的配置包含您所请求的信息。

logging:
  level:
    root: DEBUG
    org:
      hibernate: 
        SQL: DEBUG
        type.descriptor.sql.BasicBinder: TRACE
      springframework: DEBUG

如果您需要除建议之外的其他日志级别(或输出格式)。

boot.2.3.7_jdbc_ROOT.log.gz boot.2.3.6_jdbc_ROOT.log.gz

正如已经提到的。在日志中查找差异的最简单方法是搜索 _PROPERTY EXTENSION

5

谢谢。在 2.3.6 上,该data.sql脚本位于target/test-classes

09:10:22.671 DEBUG - [  task-2] o.s.jdbc.datasource.init.ScriptUtils    :572-Executing SQL script from URL [file:/home.local/lw/workspace-documat/documat-backend/target/test-classes/data.sql]

2.3.7 中没有这样的日志行。这给了我们一些值得关注的东西。

该线程task-2很有趣,与 2.3.7 日志有显着差异,在 2.3.7 日志中一切都发生在main.这是由于https://github.com/spring-projects/spring-boot/issues/24249造成的,但不应影响data.sql脚本的发现。我认为我们至少现在可以忽略这一点。

据我从提供的日志中可以看出,该data.sql脚本不在类路径中,即target/test-classes应用程序运行时它不在类路径中。如果没有样本让我能够进行调查,您将不得不自己进行调查。如果我是您,我会通过在 Spring Boot 2.3.7 上使用断点调试应用程序来开始调查org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer.getResources(String, List<String>, boolean)。深入了解SortedResourcesFactoryBean其执行的工作ResourcePatternResolver应该可以让您了解正在发生的事情。TRACE级别日志记录org.springframework.core.io.support也可能提供信息。

6

我个人仅谈几点:

  • 我们有几个配置相似的项目 - 即我们有一些具有一些配置和测试的子项目
  • 直到 2.3.6,我们都根据 docu 和多个平台上的可用内容设置了测试。
  • 我高度怀疑 #24497 是根本原因的主要候选者之一 - 无论是这样还是其他方式。我不会将其视为纪录片,而是将其视为突破性的改变。
  • 我高度假设其他(大)公司的其他项目也以类似的方式构建他们的项目,因此我预计使用 2.3.6 运行的代码仍然可以在更高版本以及 2.4.x 中运行

我的一般性发言结束。

问题聚焦:yml您要查找的详细信息,请下次提供具体配置。我仍然不确定我是否正确配置了日志。

你提到我应该在 2.3.7 中设置一个断点 - 我这样做了。它在 2.3.6 中也停止了。为了DefaultListableBeanFactory。但下面的截图仅在2.3.6可用。

图片 2021-01-14 10-46-42 boot.2.3.6_jdbc_core.log.gz boot.2.3.7_jdbc_core.log.gz

9

我自己做了一些调试,并在 org.springframework.context.support.AbstractApplicationContext 第 361 行设置了一个断点:

@Override
public void publishEvent(ApplicationEvent event) {
  publishEvent(event, null);
}

因为event我得到

  • 2.3.7 org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.web.context.support.GenericWebApplicationContext@10fbbdb, started on Thu Jan 14 12:56:38 CET 2021]

  • 2.3.6 org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.web.context.support.GenericWebApplicationContext@57a2ed35, started on Thu Jan 14 12:59:35 CET 2021]

org.springframework.boot.autoconfigure.jdbc.DataSourceSchemaCreatedEvent[source=HikariDataSource (HikariPool-1)]

进一步挖掘org.springframework.orm.jpa.AbstractEntityManagerFactoryBean#buildNativeEntityManagerFactory

  JpaVendorAdapter jpaVendorAdapter = getJpaVendorAdapter();
  if (jpaVendorAdapter != null) {
    jpaVendorAdapter.postProcessEntityManagerFactory(emf);
  }
  • 2.3.7 jpaVendorAdapter=== org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter@6f4d2294 >
    AbstractJpaVendorAdapter
    @Override
    public void postProcessEntityManagerFactory(EntityManagerFactory emf) {
    }
  • 2.3.6 jpaVendorAdapter=org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher$DataSourceSchemaCreatedPublisher@53c613f7
org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher

@Override
public void postProcessEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
    this.delegate.postProcessEntityManagerFactory(entityManagerFactory);
    AsyncTaskExecutor bootstrapExecutor = this.factoryBean.getBootstrapExecutor();
    if (bootstrapExecutor != null) {
        DataSourceInitializedPublisher.this.initializationCompletionListener.dataSourceInitialization = bootstrapExecutor
                .submit(() -> DataSourceInitializedPublisher.this.publishEventIfRequired(this.factoryBean,
                        entityManagerFactory));
    }
}

为了完整起见,我还包含了具有以下设置的日志文件。

logging:
  level:
    #root: DEBUG
    org:
      hibernate: 
        SQL: DEBUG
        type.descriptor.sql.BasicBinder: TRACE
      springframework: 
        jdbc: DEBUG
        core:
          io: TRACE
        orm: TRACE  

boot.2.3.7.ormTRACE.log.gz boot.2.3.6.ormTRACE.log.gz

2

谢谢。

24497 与此无关,因为它涉及 2.4.x 中所做的更改,并且此问题出现在 2.3.7 中。请让我们将这个问题集中在一个问题上。

失踪的事情DataSourceSchemaCreatedEvent很有趣。它应该作为LocalContainerEntityManagerFactoryBean创建的结果而被发布。以下是我的 IDE 调试器在发生这种情况时捕获的堆栈跟踪:

Thread [main] (Suspended)   
    owns: ConcurrentHashMap<K,V>  (id=125)  
    owns: Object  (id=133)  
    AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 361 
    DataSourceInitializedPublisher.publishEventIfRequired(LocalContainerEntityManagerFactoryBean, EntityManagerFactory) line: 110   
    DataSourceInitializedPublisher.postProcessAfterInitialization(Object, String) line: 101 
    DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyBeanPostProcessorsAfterInitialization(Object, String) line: 430 
    DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).initializeBean(String, Object, RootBeanDefinition) line: 1798    
    DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 594 
    DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).createBean(String, RootBeanDefinition, Object[]) line: 516   
    DefaultListableBeanFactory(AbstractBeanFactory).lambda$doGetBean$0(String, RootBeanDefinition, Object[]) line: 324  
    409598930.getObject() line: not available   
    DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String, ObjectFactory<?>) line: 234   
    DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 322    
    DefaultListableBeanFactory(AbstractBeanFactory).getBean(String) line: 202   
    AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).getBean(String) line: 1109   
    AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 869   
    AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).refresh() line: 551  
    AnnotationConfigServletWebServerApplicationContext(ServletWebServerApplicationContext).refresh() line: 143  
    SpringApplication.refresh(ConfigurableApplicationContext) line: 758 
    SpringApplication.refresh(ApplicationContext) line: 750 
    SpringApplication.refreshContext(ConfigurableApplicationContext) line: 405  
    SpringApplication.run(String...) line: 315  
    SpringApplication.run(Class<?>[], String[]) line: 1237  
    SpringApplication.run(Class<?>, String...) line: 1226   
    SampleDataJpaApplication.main(String[]) line: 26

您能否使用调试器来确定事件何时尚未发布?

7

我不明白你在找什么。如前所述 -HibernateJpaVendorAdapter不包含任何方法。因此没有Event创建。嗯...我想我太快了并且已经回答了你的问题:-)

6

根据所使用的初始化类型,该事件会在几个不同的地方发布。在这种情况下,我们感兴趣的地方是上面堆栈中显示的地方:

https://github.com/spring-projects/spring-boot/blob/aa15a1d6d84292d4b8c96acf0384a2a9a5596ee0/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/ DataSourceInitializedPublisher.java#L98-L102

这是 Spring Boot 2.3.7 中的代码,调用publishEventIfRequired 应该触发事件的发布。

6

抱歉,如果我坚持的话 - 但我仍然猜......

无论如何……在 Spring Boot 2.3.7 中。我既没有打到 90、93、96 也没有打到 99 号线。

在 Spring Boot 2.3.6 中。我击中了所有人 - 在我击中之前org.springframework.orm.jpa.AbstractEntityManagerFactoryBean#buildNativeEntityManagerFactory

那么,接下来您需要什么样的信息?

4

这表明LocalContainerEntityManagerFactoryBean正在过早初始化,因此不符合 的后处理条件DataSourceInitializedPublisher。我们需要一个重现问题的示例来确定为什么会出现这种情况。或者,您可以使用带有断点的调试器来org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.entityManagerFactory(EntityManagerFactoryBuilder)准确查看 bean 的创建时间并逐步执行其后处理。

1

抱歉,但我怀疑这JpaBaseConfiguration.entityManagerFactory是正确的位置。因为在 2.3.6 中,这是在被击中之后 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean#buildNativeEntityManagerFactory被击中的。但在2.3.7中。事实恰恰相反。

为什么顺序从 2.3.6 ==> 2.3.7 变了?这有什么关系吗?

是的,一个样本会很棒 - 但老实说我不知道​​要包含什么以及要提供什么。

1

顺序不应改变。该entityManagerFactory @Bean方法应该创建LocalContainerEntityManagerFactoryBean并返回它。然后应该初始化该 bean,此时afterPropertiesSet()调用它,然后调用buildNativeEntityManagerFactory().如果buildNativeEntityManagerFactory()在该方法之前调用entityManagerFactory @Bean,我能想到的唯一解释是您的应用程序中有多个实体管理器工厂。此外,如果org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.entityManagerFactory(EntityManagerFactoryBuilder)仍在调用,则必须在 后运行的自动配置中定义附加实体管理器工厂HibernateJpaAutoConfiguration,否则 Boot 的自动配置实体管理器工厂应该退出。

不幸的是,根据您目前能够提供的信息,我认为我没有理由再花更多的时间来帮助您。仅从日志文件中几乎不可能推断出应用程序的结构和组件。如果您无法提供重现问题的最小示例,那么也许您可以通过 GitHub 上的私有存储库或类似的存储库提供对应用程序本身的访问,以及重现问题所需的步骤?

9

如果您希望我们查看此问题,请提供所需的信息。如果在接下来的 7 天内未提供信息,此问题将被关闭。

2

由于缺乏所需的反馈而关闭。如果您希望我们查看此问题,请提供所需的信息,我们将重新打开该问题。