我想以编程方式创建Custom DataSource。这是因为我想在运行时从安全存储中获取密码,而不是在application.yaml中对其进行硬编码。
我有一个自定义数据源 - myapp.datasource.password,其值为mydb.password.key。使用ApplicationListener我正在加载机密并使用mydb.password.key作为键设置myapp.datasource.password的值。
myapp:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mydb?autoReconnect=true&characterEncoding=utf8
username: myuser
password: mydb.password.key
现在,HibernateJpaAutoConfiguration正在尝试使用mydb.password.key作为密码连接到数据库,并在启动时失败。
我尝试排除数据库自动配置类
@SpringBootApplication
(exclude={
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
但它抛出了这个异常
org.springframework.beans.factory.NoSuchBeanDefinitionException:没有名为'entityManagerFactory'的bean可用
如何解决这个问题?非常感谢任何帮助!
谢谢
答案 0 :(得分:3)
无需排除内置的自动配置。
在你的application.yml
中myapp:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mydb?autoReconnect=true&characterEncoding=utf8
username: myuser
# make sure you exclude password from here
在您的配置中:
// all the other datasource properties will be applied from "myapp.datasource" except password because you excluded it
@ConfigurationProperties(prefix = "myapp.datasource")
@Bean
@Primary // this will override the datasource autoconfiguration and use your own everywhere
public DataSource dataSource() {
String password = retrieveMyPasswordSecurely();
return DataSourceBuilder
.create()
.password(password)
.build();
}
答案 1 :(得分:0)
您需要提供Entity Manager Factory bean。您可以遵循创建名为entityManagerFactory的bean的约定,假设您还没有。 Spring documentation here和here中有几个例子。
假设您有一个数据源,您可以尽可能少地逃脱:
@Configuration
public class Database {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("org.yourcompany.jpaentityroot");
factory.setDataSource(dataSource);
return factory;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(emf);
return txManager;
}
@Resource private DataSource dataSource;
}