[英]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.