Java 如何通过环境变量设置名称中带有下划线的Spring启动属性?

Java 如何通过环境变量设置名称中带有下划线的Spring启动属性?,java,spring,spring-boot,Java,Spring,Spring Boot,我想在Spring Boot应用程序中设置hibernate.format\u sql。我想使用环境变量设置它 Spring Boot相当方便地将所有环境变量从Spring上下文中的FOO\u BAR\u BAZ转换为名为FOO.BAR.BAZ的属性 在Spring Boot中,如何使用环境变量设置目标名称中带有下划线的属性?大概HIBERNATE\u FORMAT\u SQL将被翻译成HIBERNATE.FORMAT.SQL?结果是SPRING\u JPA\u SHOW\u SQL=true工

我想在Spring Boot应用程序中设置hibernate.format\u sql。我想使用环境变量设置它

Spring Boot相当方便地将所有环境变量从Spring上下文中的
FOO\u BAR\u BAZ
转换为名为
FOO.BAR.BAZ
的属性


在Spring Boot中,如何使用环境变量设置目标名称中带有下划线的属性?大概
HIBERNATE\u FORMAT\u SQL
将被翻译成
HIBERNATE.FORMAT.SQL

结果是
SPRING\u JPA\u SHOW\u SQL=true
工作正常。我不知道这是否意味着该特定属性的名称被重载,或者Spring是否正在做一些更聪明的事情。它解决了我的问题,并为我所问的示例提供了所需的行为。

这是一个老问题,但我会回答它,以防其他人(如我)在这里查找此信息

HIBERNATE\u FORMAT\u SQL应该可以做到这一点

实际上,“转换”的不是OS环境变量,而是Spring属性名

名称以多种方式翻译,并根据可用的环境变量进行查找。例如,“hibernate.format.sql”被查找为:

  • hibernate.format.sql(按原样)
  • hibernate_格式_sql(点替换为下划线)
  • hibernate_format_sql(破折号替换为下划线,与您的情况相同)
  • hibernate_format_sql(破折号和点替换为下划线,与您的情况相同)
  • 大写字母也一样:

  • HIBERNATE.FORMAT.SQL(按原样)
  • HIBERNATE_格式_SQL(点替换为下划线)
  • HIBERNATE_FORMAT_SQL(破折号替换为下划线,再次相同)
  • HIBERNATE_FORMAT_SQL(用下划线替换虚线和点,再次相同)
  • 虽然不能使用set或export命令设置名称中带有点的环境变量,但使用env命令也可以。我推迟判断这是否是一个好主意:

    env "my.dotted.name=\"a value\"" the-command-you-want-to-run
    
    看看 详情请参阅。我链接到一个特定的版本,但您应该确保查看您正在使用的版本

    要解决生产环境中的此类问题,可以尝试打开属性解析代码的调试日志:

    logging:
      level:
        org.springframework.core.env: DEBUG
    
    。。。或者通过设置适当的环境变量:)

    编辑: 我强烈建议您熟悉相关的Spring Boot文档主题:

    对于此处注释中更棘手的示例,例如
    spring.jpa.properties.hibernate.criteria.literal\u handling\u mode
    ,可能有不同的解决方案,具体取决于启动应用程序的方式

    您可以将变量设置为JSON,嵌入到环境变量中

    env SPRING_APPLICATION_JSON='{"spring":{"jpa":{"properties":{"hibernate":{"criteria":{"literal_handling_mode":"BIND"}}}}}}' ./gradlew bootRun
    
    简单地按原样设置变量也可以:

    env spring.jpa.properties.hibernate.criteria.literal_handling_mode=BIND ./gradlew bootRun
    
    以上两种方法在我的设置中都有效,因为我能够通过以下方式在运行的Spring Boot应用程序中获得值:

    @Value(${spring.jpa.properties.hibernate.criteria.literal\u handling\u mode})
    通过vvariable设置私有字符串测试;
    

    希望这有帮助!YMMV

    我也遇到了同样的问题,环境变量
    spring\u jpa\u properties\u hibernate\u default\u schema
    Spring将其翻译为
    Spring.jpa.properties.hibernate.default.schema
    ,但hibernate需要
    hibernate.default\u schema

    出于某种原因(devops问题),我无法将其更改为
    spring.jpa.properties.hibernate.default\u schema
    ——它在本地机器上工作

    我是这样解决的

    @Component
    public class HibernateConfig implements HibernatePropertiesCustomizer {
    
        private final static String HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM = "hibernate.default.schema";
    
        @Override
        public void customize(Map<String, Object> hibernateProperties) {
            if (hibernateProperties.containsKey(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM)) {
                hibernateProperties.put(AvailableSettings.DEFAULT_SCHEMA, hibernateProperties.get(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM));
            }
        }
    }
    
    @组件
    公共类HibernateConfig实现HibernatePropertiesCustomizer{
    私有最终静态字符串HIBERNATE\u CUSTOM\u DEFAULT\u SCHEMA\u PARAM=“HIBERNATE.DEFAULT.SCHEMA”;
    @凌驾
    公共void自定义(映射hibernateProperties){
    if(hibernateProperties.containsKey(HIBERNATE\u CUSTOM\u DEFAULT\u SCHEMA\u PARAM)){
    hibernateProperties.put(AvailableSettings.DEFAULT_模式,hibernateProperties.get(HIBERNATE_自定义_默认_模式_参数));
    }
    }
    }
    
    hibernate属性的名称并不重要,重要的是用于检索该属性的名称(为什么保持不变?)。只要给它一个不管“或”如何都能工作的名称。“为什么保持它们不变?”:因为他想设置Hibernate属性。这无关紧要。您可以在您的环境中命名属性foo,然后仍然为hibernate设置
    hibernate.format\u sql
    属性。它们不必是相同的。例如
    foo
    就是一个例子。我不想设置名为
    foo
    的属性。我想使用环境变量设置
    hibernate.format\u sql
    。属性名称中的大小写无关紧要-整个名称只是大写。我想设置spring.jpa.properties.hibernate.criteria.literal\u handling\u mode=BIND via ENV参数,但它不起作用。当我在整个ENV设置中使用下划线时,它们在到达服务时会变成点(当然,它们没有被hibernate正确拾取),我们在spring.jpa.properties.hibernate.globally_quoted_标识符上也有同样的问题。我最终在SpringApplicationBuilder上直接用Java进行了设置。虽然它的财产是好的,但它不为其他人@hecko84你找到解决问题的方法了吗?@Marceau,没有,很抱歉,没有办法用环境设置覆盖它。我现在在application.properties中设置了它,它与docker映像中的jar捆绑在一起。最后,对于这个参数,它是这样的,因为无论如何都没有理由要覆盖它。此外,通过这样做,我们可以防止我们的OPs人员干扰服务:D