【问题标题】:How to start spring-boot app without depending on Database?如何在不依赖数据库的情况下启动 spring-boot 应用程序?
【发布时间】:2023-03-15 07:40:02
【问题描述】:

我正在为我的应用程序使用“Spring-boot + Hibernate4 + mysql”。作为其中的一部分,我有一个要求,即使数据库关闭,我的 sprint-boot 应用程序也应该能够启动。目前,当我尝试在 DB 未启动的情况下启动我的 Spring Boot 应用程序时,它会给出以下异常。

我研究了很多,发现这个异常与hibernate.temp.use_jdbc_metadata_defaults属性有关。

我尝试在 spring boot 的“application.yml”中设置这个,但是这个属性的值没有在运行时反映。

异常堆栈跟踪:

2014-05-25 04:09:43.193  INFO 59755 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
2014-05-25 04:09:43.250  WARN 59755 --- [           main] o.h.e.jdbc.internal.JdbcServicesImpl     : HHH000342: Could not obtain connection to query metadata : Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
2014-05-25 04:09:43.263  INFO 59755 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat

Error starting ApplicationContext. To display the auto-configuration report enabled debug logging (start with --debug)


Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at admin.Application.main(Application.java:36)
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:104)
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:71)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:205)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:89)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:150)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 15 more

application.yml:

spring:   
  jpa:
show-sql: true
hibernate:
  ddl-auto: none
  naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
  temp:
    use_jdbc_metadata_defaults: false

【问题讨论】:

    标签: mysql spring jpa spring-boot hibernate-4.x


    【解决方案1】:

    这确实是一个难以破解的难题。

    经过大量研究并实际调试 spring-boot、spring、hibernate、tomcat 池等以完成它。

    我确实认为这将为尝试实现此类要求的人们节省大量时间。

    以下是实现以下要求所需的设置

    1. 即使 DB 已关闭或没有 DB,Spring Boot 应用程序也能正常启动。
    2. 应用程序将在 DB 启动时即时获取连接,这意味着无需重新启动 Web 服务器或重新部署应用程序。
    3. 如果 DB 从运行状态关闭并再次启动,则无需启动 tomcat 或重新部署应用程序。

    application.yml:

    spring:
      datasource:
        driverClassName: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/schema
        username: root
        password: root
        continueOnError: true
        initialize: false
        initialSize: 0
        timeBetweenEvictionRunsMillis: 5000
        minEvictableIdleTimeMillis: 5000
        minIdle: 0
    
      jpa:
        show-sql: true
        hibernate:
          ddl-auto: none
          naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
        properties:
          hibernate:   
            dialect: org.hibernate.dialect.MySQL5Dialect
            hbm2ddl:
              auto: none
            temp:
              use_jdbc_metadata_defaults: false
    

    【讨论】:

    • 这个确实为我节省了很多时间。谢谢老兄。
    • 感谢您的代码。我必须对 EclipseLink 做同样的事情,而要做的只是 <property name="eclipselink.validation-only" value="true"/> in persistence.xml
    • 现在不推荐使用提到的道具。 @ripu 你知道什么是新属性吗?
    • 我需要的唯一设置是spring.jpa.database-platform
    【解决方案2】:

    我在这里回答并将关闭the issue that you have cross-posted

    JPA 实现(Hibernate)的任何“本机”属性都可以使用 spring.jpa.properties 前缀设置为 explained here

    我在这里的实际问题没有进一步研究,但要回答这个特定问题,您可以按如下方式设置休眠键

    spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults
    

    【讨论】:

    • 谢谢。它修复了设置“use_jdbc_metadata_defaults”属性的问题。但是,如果您看到我的帖子,实际问题是“即使数据库关闭,启动 sprint-boot 应用程序也应该能够启动”,这不是通过设置来解决的。
    • 明确一点,这与 Spring boot 无关。 Boot 只为您提供了一种配置底层休眠基础设施的机制,如果您自己配置(即手动),您将遇到完全相同的问题。感谢您分享配置!
    【解决方案3】:

    单独添加这个对我有用:

    spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.Oracle10gDialect
    

    只需将最后一部分替换为您的数据库方言即可。

    【讨论】:

      【解决方案4】:

      该解决方案对我非常有用。谢谢 我使用的文件“application.properties”包括以下几行:

          app.sqlhost=192.168.10.11
          app.sqlport=3306
          app.sqldatabase=logs
      
          spring.main.web-application-type=none
      
          # Datasource
          spring.datasource.url=jdbc:mysql://${app.sqlhost}:${app.sqlport}/${app.sqldatabase}
          spring.datasource.username=user
          spring.datasource.password=password
          spring.datasource.driver-class-name=com.mysql.jdbc.Driver
          spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
          spring.jpa.properties.hibernate.hbm2dll.auto = none
          spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
      
          spring.datasource.continue-on-error=true
          spring.datasource.initialization-mode=never
      
          spring.datasource.hikari.connection-timeout=5000
          spring.datasource.hikari.idle-timeout=600000
          spring.datasource.hikari.max-lifetime=1800000
          spring.datasource.hikari.initialization-fail-timeout= -1
      
          spring.jpa.hibernate.use-new-id-generator-mappings=true
          spring.jpa.hibernate.ddl-auto=none
      
          spring.jpa.show-sql=true
      
          spring.output.ansi.enabled=always
      

      但是,你不能在类级别使用@Transactional注解

      @Service
      //@Transactional  //do not use to touch the Repository
      @EnableAsync
      @Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
      public class LogService {
      .... }
      
      @Async
      @Transactional  // you can use at function level
      public void deleteLogs(){
          logRepository.deleteAllBy ...
      }
      

      【讨论】:

        【解决方案5】:

        添加以下配置应该可以工作:

        spring.jpa.database-platform: org.hibernate.dialect.MySQL5Dialect

        【讨论】:

          猜你喜欢
          • 2017-04-29
          • 1970-01-01
          • 2019-07-22
          • 2019-11-04
          • 2018-09-07
          • 2020-02-23
          • 2021-12-21
          • 1970-01-01
          相关资源
          最近更新 更多