当前位置: 首页 > 知识库问答 >
问题:

使用CrudRepository时不调用自定义DynamoDb TableNameResolver

牟稳
2023-03-14

我正在测试DynamoDB表,希望使用关键字“dev”为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 in production的表来实现的。

但是,我有一个包含以下代码的存储库

@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);

}

因此,当我试图通过endpoint/测试用例调用findAll方法时,我得到了异常

出现意外错误(type=内部服务器错误,状态=500)。user: arn: aws: iam::87668976786: user/svc_nac_ps_MyProjectName_prod未被授权执行: Dynamodb: Scan on resource::/abc_xy_dev_MyProjectName_Employee(服务: Amazon DynamoDBv2;状态代码: 400;错误代码: AccessDeniedExcture;请求ID: aksdnhLDFL)

i、 执行respository方法时,不会在内部调用MyTableNameResolver。它仍然指向在注释@DynamoDBTable(tableName=“abc_xy_dev_MyProjectName_Employee”)中给出的名为abc_xy_dev_MyProjectName_Employee”的表名

共有2个答案

马绪
2023-03-14

您正在使用DynamoDBMapper(JavaSDK)。下面是我如何使用它。假设我有一个名为用户的表,其中有一个关联的用户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);

希望有帮助。

马凡
2023-03-14


下面的配置可以用来设置表名覆盖,作为Spring引导配置的一部分。

示例见https://github.com/ganesara/SpringExamples/tree/master/spring-dynamo

使用用户定义的映射器配置参考映射Dynamo db存储库

@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());
    }
}
 类似资料:
  • 我读到了Crudrepository,这是一个接口,用于在特定类型的存储库上进行通用CRUD操作。 但是我们可以创建我们的自定义接口并扩展CrudRepository。

  • 我使用以下代码在woocommerce结帐中添加自定义订单字段: 然后,后面跟着下面的代码,用字段值更新order meta:

  • 我在网上搜索了一个关于如何使用Spring AOP调用自定义方法注释的清晰示例,但没有找到一个清晰的示例。 我正在构建一个框架,以便在调用任何POJO上的某些方法时在上下文中注入用户配置文件。 框架API应该通过自定义方法注释调用,例如。我可以构建注释部分和解析器,我的问题是在调用带注释的方法时调用我的解析器的最佳方式是什么。 我们正在使用Spring 3.0,想知道配置Spring框架以理解那些

  • $this->db->call_function(); 这个方法用于执行一些 CodeIgniter 中没有定义的 PHP 数据库函数,而且 使用了一种平台独立的方式。举个例子,假设你要调用 mysql_get_client_info() 函数,这个函数 CodeIgniter 并不是原生支持的,你可以这样做: $this->db->call_function('get_client_info')

  • 问题内容: 我试图在扩展CrudRepository的存储库中执行一些SQL查询。我在控制器中有以下代码: DAO代码如下: 该类是: 投影为: 我对如何添加查询(诸如此类)感到困惑: 我如何更改投影,还有哪些其他必要的更改? 问题答案: 您可以将DAO更改为下面,这应该可以工作。 } 确保Bean类构造函数应具有传递的参数。 验证查询是否为有效的JPA查询(此处)。

  • 我应该如何构建findBy方法名,以便实现where子句- 这是一种选择吗? 如果我只想传递一个字符串而不是一个列表呢? 非常感谢。