[英]Set schema name at run time using REST API input in spring boot based application
在postgres数据库中,模式名称被设置为买家 ID (因此,如果买家 ID 是buyer_2213,那么模式名称将是buyer_2213 )。 这些模式有多个表,并且这些表具有所有模式的通用结构。
现在,我正在使用 Spring Boot 编写 REST API 以从这些架构中获取买家数据,但由于架构名称依赖于买家 ID ,因此我必须编写手动查询并且无法为此使用 JPA 功能。
有什么方法可以使用 REST API 请求参数将架构名称设置为实体。 因此,在下面的实体中,我们可以使用在buyerController 中定义的API 调用中传递的buyerId来设置模式:
@Entity
@Table(name="buyer_table", schema="set_it_using_API_input")
public class BuyerTable{
...
}
@RestController
@RequestMapping("/buyer")
public class BuyerController{
@GetMapping("/{buyerId}")
public void getBuyerData(@PathVariable(required = true) String buyerId){
...
}
}
此外,买家 ID 与登录用户不同(将此情况视为尝试获取买家详细信息的管理员用户),并且将仅作为 API 请求参数提供(或作为 API 输入的任何其他方式)。 因此我找不到与此相关的内容
我终于找到了一个可行的解决方案。 此解决方案主要使用此处的配置,但更具体地针对我的问题要求。
这个想法显然是使用AbstractDataSource并且数据源配置与此处显示的非常相似,只是模式名称将使用可以从 API 逻辑内部调用的setter 设置。
首先,我们需要编写一个AbstractDataSource的实现,它看起来像这样:
public class BuyerSchemaDataSource extends AbstractDataSource {
private LoadingCache<String, DataSource> dataSources = createCache();
public void setSchemaName(String schemaName){
this.schemaName = schemaName;
}
@Override public Connection getConnection() throws SQLException {
try {
return determineTargetDataSource().getConnection();
} catch (ExecutionException e) {
//print exception
return null;
}
}
@Override public Connection getConnection(String username, String password)
throws SQLException {
try {
return determineTargetDataSource().getConnection(username,password);
} catch (ExecutionException e) {
//print exception
return null;
}
}
private DataSource determineTargetDataSource() throws ExecutionException {
if(!utils.isNullOrEmpty(schemaName)){
return dataSources.get(schemaName);
}
return buildDataSourceFromSchema(null);
}
private LoadingCache<String, DataSource> createCache(){
return CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<String, DataSource>() {
@Override public DataSource load(String key) throws Exception {
return buildDataSourceFromSchema(key);
}
});
}
private DataSource buildDataSourceForSchema(String schema) {
// e.g. of property: "jdbc:postgresql://localhost:5432/mydatabase?currentSchema="
String url = env.getRequiredProperty("spring.datasource.url") + schema;
return DataSourceBuilder.create()
.driverClassName(env.getRequiredProperty("spring.datasource.driverClassName"))
[...]
.url(url)
.build();
}
}
@Configuration @EnableTransactionManagement @EnableJpaRepositories(entityManagerFactoryRef = "schemaSpecificEntityManagerFactory", transactionManagerRef = "schemaSpecificTransactionManager") public class SchemaSpecificConfig { @Bean(name = "schemaSpecificDataSource") public DataSource schemaSpecificDataSource(){ return new BuyerSchemaDataSource(); } @Bean(name = "schemaSpecificEntityManagerFactory") public LocalContainerEntityManagerFactoryBean schemaSpecificEntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("schemaSpecificDataSource") DataSource dataSource) { HashMap<String, Object> properties = new HashMap<>(); properties.put("hibernate.hbm2ddl.auto", "update"); properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect"); return builder.dataSource(dataSource).properties(properties) .persistenceUnit("SchemaSpecific").build(); } @Bean(name = "schemaSpecificTransactionManager") public PlatformTransactionManager schemaSpecificTransactionManager( @Qualifier("schemaSpecificEntityManagerFactory") EntityManagerFactory schemaSpecificEntityManagerFactory) { return new JpaTransactionManager(schemaSpecificEntityManagerFactory); } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.