(解决方法)在实体上使用@ConditionalOnProperty
(Workaround for) Use of @ConditionalOnProperty on Entity
我们有一个 Spring- 带有一些数据库实体的启动应用程序-类。
我们使用 ddl-auto: validate
来确保连接的数据库具有正确的架构。
现在我们要添加一个可以切换以匹配不同环境的功能,NewFeatureService 注释为 @ConditionalOnProperty("newfeature.enabled")
。
到这里为止一切正常。
问题是该功能需要数据库实体。
@Entity
@ConditionalOnProperty("newfeature.enabled") // <--- doesn't work
public class NewFeatureEnitity{...}
@ConditionalOnProperty
显然不起作用,但是如果设置了 属性,告诉 Hibernate 仅针对数据库验证此实体的好方法是什么。
我们不想要的:
- 在所有数据库中添加此 table 即使未使用该功能
- 有不同的工件
Hibernate 会将每个 @Entity class 视为一个实体,只要 class/package 包含在 Hibernate 设置中。
但是,Spring 提出了方便(和简单)的解决方案,所以正如您提到的,您可以使用 @ConditionalOnProperty(我假设您正在为 Spring 使用 java 配置):
在您的 Hibernate 配置中 class :
@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
将在此数组中组合所有定义的字符串 bean(我假设您没有定义任何其他字符串 bean),因此您可以为其他功能添加尽可能多的字符串 bean,您可以检查 documentation了解更多详情。
重点是将新功能包与通用包分开,使通用包不是父包。
为了确保它不受监督,我想提供我的建议作为答案。
它比 提供的答案更多地使用了 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.
*/
}
我们有一个 Spring- 带有一些数据库实体的启动应用程序-类。
我们使用 ddl-auto: validate
来确保连接的数据库具有正确的架构。
现在我们要添加一个可以切换以匹配不同环境的功能,NewFeatureService 注释为 @ConditionalOnProperty("newfeature.enabled")
。
到这里为止一切正常。
问题是该功能需要数据库实体。
@Entity
@ConditionalOnProperty("newfeature.enabled") // <--- doesn't work
public class NewFeatureEnitity{...}
@ConditionalOnProperty
显然不起作用,但是如果设置了 属性,告诉 Hibernate 仅针对数据库验证此实体的好方法是什么。
我们不想要的:
- 在所有数据库中添加此 table 即使未使用该功能
- 有不同的工件
Hibernate 会将每个 @Entity class 视为一个实体,只要 class/package 包含在 Hibernate 设置中。 但是,Spring 提出了方便(和简单)的解决方案,所以正如您提到的,您可以使用 @ConditionalOnProperty(我假设您正在为 Spring 使用 java 配置):
在您的 Hibernate 配置中 class :
@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
将在此数组中组合所有定义的字符串 bean(我假设您没有定义任何其他字符串 bean),因此您可以为其他功能添加尽可能多的字符串 bean,您可以检查 documentation了解更多详情。
重点是将新功能包与通用包分开,使通用包不是父包。
为了确保它不受监督,我想提供我的建议作为答案。
它比
您可以将 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.
*/
}