我正在测试DynamoDB表,并想使用关键字“ dev ”进行开发,并使用 prod 进行生产并为prod和dev环境设置不同的表名。
我有一个POJO
@DynamoDBTable(tableName = "abc_xy_dev_MyProjectName_Employee")
public class Employee implements Cloneable {
}
在Prod上,我希望它的名称为abc_xy_prod_MyProjectName_Employee。
所以,我写了一个TableNameResolver
public static class MyTableNameResolver implements TableNameResolver {
public static final MyTableNameResolver INSTANCE = new MyTableNameResolver();
@Override
public String getTableName(Class<?> clazz, DynamoDBMapperConfig config) {
final TableNameOverride override = config.getTableNameOverride();
String tableNameToReturn = null;
if (override != null) {
final String tableName = override.getTableName();
if (tableName != null) {
System.out.println("MyTableNameResolver ==================================");
return tableName;
}
}
String env = System.getenv("DEPLOYMENT_ENV");
for(Annotation annotation : clazz.getAnnotations()){
if(annotation instanceof DynamoDBTable){
DynamoDBTable myAnnotation = (DynamoDBTable) annotation;
if ("production".equals(env)){
tableNameToReturn = myAnnotation.tableName().replace("_dev_", "_prod_");
}
else {
tableNameToReturn = myAnnotation.tableName();
}
}
}
return tableNameToReturn;
}
}
这可以通过在生产环境中创建一个名称为abc_xy_prod_MyProjectName_Employee的表来实现。
但是,我有一个包含以下代码的存储库
@EnableScan
public interface EmployeeRepository extends CrudRepository<Employee, String>
{
@Override
<S extends Employee> S save(S employee);
Optional<Employee> findById(String id);
@Override
List<Employee> findAll();
Optional<Employee> findByEmployeeNumber(String EmployeeNumber);
}
因此,当我尝试通过端点/测试用例调用方法findAll时,我得到了异常
发生意外错误(类型=内部服务器错误, 状态= 500)。用户: arn:aws:iam :: 87668976786:user / svc_nac_ps_MyProjectName_prod不是 被授权执行:dynamodb:扫描资源: :table / abc_xy_dev_MyProjectName_Employee(服务:AmazonDynamoDBv2; 状态码:400;错误代码:AccessDeniedException;要求编号: aksdnhLDFL)
即,执行存储库方法时,不会在内部调用MyTableNameResolver。它仍然指向在@DynamoDBTable批注中给出的名称为abc_xy_dev_MyProjectName_Employee的表名(tableName =“ abc_xy_dev_MyProjectName_Employee”)
答案 0 :(得分:1)
您正在使用DynamoDBMapper(Java SDK)。这是我的用法。可以说我有一个名为Users的表,并带有一个关联的User POJO。在DynamoDB中,我有DEV_Users和LIVE_Users。
我有一个环境变量'ApplicationEnvironmentName',它是DEV或LIVE。
我这样创建一个自定义DynamoDBMapper:
public class ApplicationDynamoMapper {
private static Map<String, DynamoDBMapper> mappers = new HashMap<>();
private static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(System.getProperty("DynamoDbRegion")).build();
protected ApplicationDynamoMapper() {
// Exists only to defeat instantiation.
}
public static DynamoDBMapper getInstance(final String tableName) {
final ApplicationLogContext LOG = new ApplicationLogContext();
DynamoDBMapper mapper = mappers.get(tableName);
if (mapper == null) {
final String tableNameOverride = System.getProperty("ApplicationEnvironmentName") + "_" + tableName;
LOG.debug("Creating DynamoDBMapper with overridden tablename {}.", tableNameOverride);
final DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig.Builder().withTableNameOverride(TableNameOverride.withTableNameReplacement(tableNameOverride)).build();
mapper = new DynamoDBMapper(client, mapperConfig);
mappers.put(tableName, mapper);
}
return mapper;
}
}
我的用户POJO如下所示:
@DynamoDBTable(tableName = "Users")
public class User {
...
}
当我想使用数据库时,我将创建一个应用程序映射器,如下所示:
DynamoDBMapper userMapper = ApplicationDynamoMapper.getInstance(User.DB_TABLE_NAME);
如果我想加载一个用户,我会这样做:
User user = userMapper.load(User.class, userId);
希望有帮助。
答案 1 :(得分:1)
您已将spring JPA用作持久性dynamoDB集成。
下面的配置可作为Spring Boot配置的一部分来设置表名称覆盖。
在https://github.com/ganesara/SpringExamples/tree/master/spring-dynamo
中找到了示例示例使用用户定义的映射器配置参考来映射Dynamo数据库存储库
@EnableDynamoDBRepositories(basePackages = "home.poc.spring", dynamoDBMapperConfigRef="dynamoDBMapperConfig")
用于表覆盖的映射器配置如下
@Bean
public DynamoDBMapperConfig dynamoDBMapperConfig() {
DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig
.Builder()
.withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix("PROD_"))
.build();
return mapperConfig;
}
完整配置供参考
@Configuration
@EnableDynamoDBRepositories(basePackages = "home.poc.spring", dynamoDBMapperConfigRef="dynamoDBMapperConfig")
public class DynamoDBConfig {
@Value("${amazon.dynamodb.endpoint}")
private String amazonDynamoDBEndpoint;
@Value("${amazon.aws.accesskey}")
private String amazonAWSAccessKey;
@Value("${amazon.aws.secretkey}")
private String amazonAWSSecretKey;
@Bean
public AmazonDynamoDB amazonDynamoDB() {
AmazonDynamoDB amazonDynamoDB
= new AmazonDynamoDBClient(amazonAWSCredentials());
if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) {
amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint);
}
return amazonDynamoDB;
}
@Bean
public AWSCredentials amazonAWSCredentials() {
return new BasicAWSCredentials(
amazonAWSAccessKey, amazonAWSSecretKey);
}
@Bean
public DynamoDBMapperConfig dynamoDBMapperConfig() {
DynamoDBMapperConfig mapperConfig = new DynamoDBMapperConfig
.Builder()
.withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix("PROD_"))
.build();
return mapperConfig;
}
@Bean
public DynamoDBMapper dynamoDBMapper() {
return new DynamoDBMapper(amazonDynamoDB(), dynamoDBMapperConfig());
}
}