![](/img/trans.png)
[英]Set global secondary index name dynamically in dynamo db using environment variable spring boot
[英]How to set tableName dynamically using environment variable in spring boot?
我使用 AWS ECS 來托管我的應用程序並使用 DynamoDB 進行所有數據庫操作。 因此,對於不同的環境,我將擁有具有不同表名的相同數據庫。 比如“dev_users”(用於Dev env)、“test_users”(用於Test env)等。(這是我們公司在不同環境下使用同一個Dynamo賬號的方式)
因此,我想使用通過“AWS ECS 任務定義”環境參數傳遞的環境變量來更改模型類的“tableName”。
例如。
我的模型類是:
@DynamoDBTable(tableName = "dev_users")
public class User {
現在,當我在測試環境中部署容器時,需要將“dev”替換為“test”。 我知道我可以使用
@Value("${DOCKER_ENV:dev}")
訪問環境變量。 但我不確定如何在課堂外使用變量。 有什么方法可以使用 docker env 變量來選擇我的表前綴?
我的意圖是這樣使用:
我知道這是不可能的。 但是有沒有其他方法或解決方法?
編輯1:
我正在研究 Rahul 的答案並面臨一些問題。 在寫問題之前,我將解釋我遵循的過程。
過程:
檢查圖像是否有錯誤:
我沒有更改我的用戶模型類中的任何內容,因為當 bean 被執行時 bean 將替換 DynamoDBTable 的名稱。 但是表名正在發生。 數據僅從模型類級別給出的表名中提取。
我在這里缺少什么?
可以通過更改的 DynamoDBMapperConfig bean 更改表名稱。
對於您必須用文字為每個表添加前綴的情況,您可以這樣添加 bean。 在您的情況下,這里的前綴可以是環境名稱。
@Bean
public TableNameOverride tableNameOverrider() {
String prefix = ... // Use @Value to inject values via Spring or use any logic to define the table prefix
return TableNameOverride.withTableNamePrefix(prefix);
}
有關更多詳細信息,請查看此處的完整詳細信息: https : //github.com/derjust/spring-data-dynamodb/wiki/Alter-table-name-during-runtime
關於在運行時更改表名的需要,我們也有同樣的問題。 我們使用的是 Spring-data-dynamodb 5.0.2,以下配置似乎提供了我們需要的解決方案。
首先我注釋了我的 bean 訪問器
@EnableDynamoDBRepositories(dynamoDBMapperConfigRef = "getDynamoDBMapperConfig", basePackages = "my.company.base.package")
我還設置了一個名為 ENV_PREFIX 的環境變量,它是 Spring 通過 SpEL 連接的。
@Value("#{systemProperties['ENV_PREFIX']}")
private String envPrefix;
然后我設置了一個 TableNameOverride bean:
@Bean
public DynamoDBMapperConfig.TableNameOverride getTableNameOverride() {
return DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(envPrefix);
}
最后,我使用 TableNameOverride 注入設置了 DynamoDBMapperConfig bean。 在 5.0.2 中,我們必須在 DynamoDBMapperConfig 構建器中設置標准的 DynamoDBTypeConverterFactory 以避免 NPE。:
@Bean
public DynamoDBMapperConfig getDynamoDBMapperConfig(DynamoDBMapperConfig.TableNameOverride tableNameOverride) {
DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
builder.setTableNameOverride(tableNameOverride);
builder.setTypeConverterFactory(DynamoDBTypeConverterFactory.standard());
return builder.build();
}
事后看來,我可以設置一個 DynamoDBTypeConverterFactory bean,它返回一個標准的 DynamoDBTypeConverterFactory 並使用 DynamoDBMapperConfig 構建器將它注入到 getDynamoDBMapperConfig() 方法中。 但這也將起作用。
我能夠實現以活動配置文件名稱為前綴的表名。
首先添加 TableNameResolver 類,如下所示,
@Component
public class TableNameResolver extends DynamoDBMapperConfig.DefaultTableNameResolver {
private String envProfile;
public TableNameResolver() {}
public TableNameResolver(String envProfile) {
this.envProfile=envProfile;
}
@Override
public String getTableName(Class<?> clazz, DynamoDBMapperConfig config) {
String stageName = envProfile.concat("_");
String rawTableName = super.getTableName(clazz, config);
return stageName.concat(rawTableName);
}
}
然后我設置 DynamoDBMapper bean,如下所示,
@Bean
@Primary
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
DynamoDBMapper mapper = new DynamoDBMapper(amazonDynamoDB,new DynamoDBMapperConfig.Builder().withTableNameResolver(new TableNameResolver(envProfile)).build());
return mapper;
}
添加了變量 envProfile,它是從 application.properties 文件訪問的活動配置文件屬性值。
@Value("${spring.profiles.active}")
private String envProfile;
我對另一個答案投了贊成票,但這里有一個想法:
創建一個包含所有用戶詳細信息的基類:
@MappedSuperclass
public abstract class AbstractUser {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
創建 2 個具有不同表名和螺旋配置文件的實現:
@Profile(value= {"dev","default"})
@Entity(name = "dev_user")
public class DevUser extends AbstractUser {
}
@Profile(value= {"prod"})
@Entity(name = "prod_user")
public class ProdUser extends AbstractUser {
}
創建一個使用映射超類的 JPA 存儲庫
public interface UserRepository extends CrudRepository<AbstractUser, Long> {
}
然后用彈簧輪廓切換植入
@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@Transactional
public class UserRepositoryTest {
@Autowired
protected DataSource dataSource;
@BeforeClass
public static void setUp() {
System.setProperty("spring.profiles.active", "prod");
}
@Test
public void test1() throws Exception {
DatabaseMetaData metaData = dataSource.getConnection().getMetaData();
ResultSet tables = metaData.getTables(null, null, "PROD_USER", new String[] { "TABLE" });
tables.next();
assertEquals("PROD_USER", tables.getString("TABLE_NAME"));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.