Reputation: 4402
We have a Spring-Boot application with some database-entity-classes.
We use ddl-auto: validate
to make sure the connected database has correct schema.
Now we are at the point where we add a feature which is toggle-able to match different environments, the NewFeatureService is annotated with @ConditionalOnProperty("newfeature.enabled")
.
Everything works fine until here.
The problem is that the feature requires a database entity.
@Entity
@ConditionalOnProperty("newfeature.enabled") // <--- doesn't work
public class NewFeatureEnitity{...}
@ConditionalOnProperty
will obviously not work but what is a good way to tell Hibernate only to validate this Entity against the database if a property is set.
What we don't want:
Upvotes: 6
Views: 3845
Reputation: 6581
Just to be sure that it's not overseen i want to provide my suggestion as an answer.
It makes a bit more use of spring-boot than the answer provided by O.Badr.
You could configure your spring-boot application to only scan your core entities like this:
@SpringBootApplication
@EntityScan("my.application.core")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
So you are able to provide your optional entities (and features) in a package like my.application.features
(feel free to use any other structure but a package outside the previously specified base package).
@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.
*/
}
Upvotes: 8
Reputation: 3141
Hibernate will consider every @Entity class as an entity, as long as the class/package is included in Hibernate setting. But, Spring came up with handy (and simple) solutions, so as you mention, you can use @ConditionalOnProperty (I assume that you're using java configuration for Spring):
In your Hibernate configuration 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
will combine all defined string beans in this array (I assume that you do not define any other string bean), so you can add as much as String bean for other features, You can check documentation for more details.
The point is to separate a newfeature package from common package in a way that the common is not a parent package.
Upvotes: 1