有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java(在实体上使用@ConditionalOnProperty的变通方法)

我们有一个带有一些数据库实体类的Spring启动应用程序

我们使用ddl-auto: validate来确保连接的数据库具有正确的模式

现在我们添加了一个能够匹配不同环境的特性,NewFeatureService用@ConditionalOnProperty("newfeature.enabled")注释

在这里之前一切正常

问题是该功能需要一个数据库实体

@Entity
@ConditionalOnProperty("newfeature.enabled")  // <--- doesn't work
public class NewFeatureEnitity{...}

@ConditionalOnProperty显然不起作用,但如果设置了属性,那么告诉Hibernate仅针对数据库验证该实体的好方法是什么呢

我们不想要的是:

  • 在所有数据库中添加此表,即使未使用此功能
  • 有不同的人工制品

共 (2) 个答案

  1. # 1 楼答案

    为了确保它不受监管,我想提供我的建议作为答案

    O.Badr提供的答案相比,它更多地使用了spring boot

    您可以将spring boot应用程序配置为只扫描核心实体,如下所示:

    @SpringBootApplication
    @EntityScan("my.application.core")
    public class Application {
    
      public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
      }
    }
    

    因此,您可以在my.application.features这样的包中提供可选的实体(和功能)(可以随意使用任何其他结构,但可以使用之前指定的基本包之外的包)

    @ConditionalOnProperty("newfeature.enabled")
    @Configuration
    @EntityScan("my.application.features.thefeature")
    public class MyFeatureConfiguration {
      /*
      * No Configuration needed for scanning of entities. 
      * Do here whatever else should be configured for this feature.
      */
    }
    
  2. # 2 楼答案

    Hibernate将考虑每个@Entity类作为实体,只要类/包包含在Hibernate设置中。 但是,Spring提供了方便(且简单)的解决方案,所以正如您所提到的,您可以使用@ConditionalOnProperty(我假设您使用的是Spring的java配置):

    在Hibernate配置类中:

    @Configuration
    ......
    public class HibernateConfig {
    
       @Bean
       @ConditionalOnProperty(name = "newfeature.enabled")
       public String newFeaturePackageToScan(){
            return "com.example.so.entity.newfeature";
       }
    
       @Bean
       public String commonPackageToScan(){
           return "com.example.so.entity.common";
       }
    
       @Bean
       public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Autowired DataSource dataSource, @Autowired  String[] packagesToScan){
            LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
            Properties jpaProperties = new Properties();
    
            jpaProperties.put(AvailableSettings.HBM2DDL_AUTO, "validate");
            jpaProperties.put(...); // other properties
    
            emf.setDataSource(dataSource);
            emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    
            emf.setJpaProperties(jpaProperties);
            emf.setPackagesToScan(packagesToScan);
    
            return emf;
       }
    
    ...
    } 
    

    @Autowired String[] packagesToScan将组合此数组中所有已定义的string bean(我假设您没有定义任何其他string bean),因此您可以为其他功能添加尽可能多的string bean,您可以查看documentation了解更多详细信息

    关键是将newfeature包与common包分开,使common不是父包