gpt4 book ai didi

java - Spring JPA : External database configuration from property file does not work

转载 作者:行者123 更新时间:2023-12-02 09:27:24 25 4
gpt4 key购买 nike

我想使用外部属性文件来加载数据库和 REST 端点信息。我试图避免 XML 配置并倾向于基于注释的配置。

我创建了 2 个类,它们都用 @Configuration 注释,并在其构造函数中使用 @Value 注释来加载属性:

RestConfiguration.java

@Configuration
public class RestConfiguration {
private final String grantType;
private final AuthenticationScheme authenticationScheme;
private final String clientId;
private final String clientSecret;
private final String accessTokenUri;

private final boolean useProxy;
private final String proxyHost;
private final int proxyPort;

@Autowired
public RestConfiguration(
@Value("${api.oauth2.grant-type}") String grantType,
@Value("${api.oauth2.authentication-scheme}") AuthenticationScheme authenticationScheme,
@Value("${api.oauth2.client-id}") String clientId,
@Value("${api.oauth2.client-secret}") String clientSecret,
@Value("${api.oauth2.url}") String accessTokenUri,
@Value("${net.proxy}") boolean useProxy,
@Value("${net.proxy.host}") String proxyHost,
@Value("${net.proxy.port}") int proxyPort) {
this.grantType = grantType;
this.authenticationScheme = authenticationScheme;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.accessTokenUri = accessTokenUri;
this.useProxy = useProxy;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
}

持久化配置.java

@Configuration
public class PersistenceConfiguration {
private final String host;
private final String port;
private final String database;
private final String schema;
private final String user;
private final String password;

@Autowired
public PersistenceConfiguration(
@Value("${db.host}") String host,
@Value("${db.port}") String port,
@Value("${db.database}") String database,
@Value("${db.schema}") String schema,
@Value("${db.user}") String user,
@Value("${db.password}") String password) {
this.host = host;
this.port = port;
this.database = database;
this.schema = schema;
this.user = user;
this.password = password;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("ch.example.rest.entities");

JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());

return em;
}

@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://" + host + ":" + port + "/" + database);
dataSource.setUsername(user);
dataSource.setPassword(password);
dataSource.setSchema(schema);
return dataSource;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);

return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}

Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "none");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect");
properties.setProperty(
"hibernate.physical_naming_strategy",
"ch.example.rest.configurations.SnakeCaseNamingStrategy");
properties.setProperty(
"spring.datasource.hikari.data-source-properties", "stringtype=unspecified");

return properties;
}
}

两个配置文件都位于同一个包中(子包configurations)。

初始化 Spring 上下文的类如下所示:

@Configuration
@ComponentScan(basePackages = "ch.example.rest")
@EnableJpaRepositories("ch.example.rest.repositories")
@PropertySource("classpath:application.properties")
public class RestClient {
private CommandLineController commandLineController;

@Autowired
public RestClient(CommandLineController commandLineController) {
this.commandLineController = commandLineController;
}

private static void main(String[] args) {
// ... some parsing of command line arguments

// Initialize context
ApplicationContext ctx = new AnnotationConfigApplicationContext(RestClient.class);
RestClient restClient = ctx.getBean(RestClient.class, uploadCommand);
restClient.runCommand(parsedCommand, uploadCommand);
}

public void runCommand(String command, UploadBillsCommand uploadCommand) {
// Some calls to a controller
commandLineController....;
}
}

有趣的是,RestConfiguration 类接收属性,但 PersistenceConfiguration 不接收这些属性。在调试过程中,我注意到 PersistenceConfiguration 类几乎是立即构建的,而 RestConfiguration 是在第一次调用 RestTemplate 时稍后加载的。

我怀疑这可能与 Spring JPA 尝试连接存储库并因此需要在启动时建立 SQL 连接有关。

我找到了this问题似乎表明,如果没有额外的样板代码,就不可能从外部提供数据库配置。由于这个问题已经有 5 年历史了,我想知道是否有另一个优雅的解决方案可以解决这个问题,而无需创建第二个上下文。

最佳答案

好吧,答案看起来很简单。我不必让 Spring 使用带有 @Value 注释的表达式语言加载属性,而是只需注入(inject)一个 Environment 实例,然后直接从中获取属性:

@Configuration
public class PersistenceConfiguration {
private String host;
private String port;
private String database;
private String schema;
private String user;
private String password;

@Autowired
public PersistenceConfiguration(Environment environment) {
this.host = environment.getProperty("db.host");
this.port = environment.getProperty("db.port");
this.database = environment.getProperty("db.database");
this.schema = environment.getProperty("db.schema");
this.user = environment.getProperty("db.user");
this.password = environment.getProperty("db.password");
}
}

关于java - Spring JPA : External database configuration from property file does not work,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58242255/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com