java - 在基于 Spring Boot 的应用程序中使用 REST API 输入在运行时设置模式名称
问题描述
在postgres数据库中,模式名称设置为买家 id(因此,如果买家 id 是buy_2213 ,那么模式名称将是buy_2213)。这些模式有多个表,并且这些表具有所有模式的通用结构。
现在,我正在使用 Spring Boot 编写 REST API 以从这些模式中获取买家数据,但由于模式名称依赖于买家 ID ,因此我必须编写手动查询并且无法使用 JPA 功能。
有没有办法使用 REST API 请求参数将架构名称设置为实体。因此,在下面的实体中,我们可以使用在BuyerController中定义的 API 调用中传递的买家 ID 来设置模式:
@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();
}
}
现在,就像任何其他数据源一样,它可以在 spring 配置文件中使用,如下所示:
@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);
}
}
现在,BuyerSchemaDataSource 中定义的 setSchema() 方法可以从控制器的 API 逻辑内部调用。
这看起来是一种不好的解决方法,但我没有找到比这更好的方法,所有建议/编辑都表示赞赏。
推荐阅读
- excel - Excel VBA ProperCase 函数
- javascript - 带有“this”参数的 TypeScript 新 Array.prototype 通用函数
- html - 预订应用程序上不同天数的不同价格
- java - Java Xmx 和 Docker 容器 RAM 大小之间还有多少余量?
- swiftui - 如何在 swiftUI 的一侧拉伸图像,如 Android 中的 .9 文件?
- firebase - 在 null 上调用了 getter 'imgUrl'
- database - 如何使只读从属 Postgresql12 数据库可写?
- java - 如何防止Java自动舍入
- google-cloud-firestore - 使用 Firestore 数据库时,在 Play Store 上发布的应用的最佳规则是什么?
- java - java如何计算数组中的重复元素