Amazon DynamoDB和类层次结构



我正在使用这个库与Spring Boot和Amazon DynamoDB合作。问题出在这个类层次结构上:

@DynamoDBTable(tableName = "EventLogs")
abstract class AbstractEventLogEntry implements Serializable {
  private static final long serialVersionUID = 7713867887326010287L;
  @DynamoDBHashKey(attributeName = "EventId")
  private String eventId;
  @DynamoDBAttribute(attributeName = "GeneratedAt")
  @DynamoDBMarshalling(marshallerClass = ZonedDateTimeMarshaller.class)
  private ZonedDateTime generatedAt;
  AbstractEventLogEntry() {
    eventId = new UUID().value();
    generatedAt = ZonedDateTime.now();
  }
  /* Getters / Setter */
}

另一类:

public abstract class EventLogEntry extends AbstractEventLogEntry {
  private static final long serialVersionUID = 1638093418868197192L;
  @DynamoDBAttribute(attributeName = "UserId")
  private String userId;
  @DynamoDBAttribute(attributeName = "EventName")
  private String eventName;
  protected EventLogEntry(AdminEvent event) {
    userId = event.getUserName();
    eventName = event.getClass().getSimpleName();
  }
  protected EventLogEntry(UserEvent event) {
    userId = event.getUserId();
    eventName = event.getClass().getSimpleName();
  }
  /* Getters / Setter */
}

另一个:

public class AdminEventLogEntry extends EventLogEntry {
  private static final long serialVersionUID = 1953428576998278984L;
  public AdminEventLogEntry(AdminEvent event) {
    super(event);
  }
}

最后一个:

public class UserEventLogEntry extends EventLogEntry {
  private static final long serialVersionUID = 6845335344191463717L;
  public UserEventLogEntry(UserEvent event) {
    super(event);
  }
}

典型的类层次结构。现在我正在尝试使用一个公共存储库来存储AdminEventLogEntryUserEventLogEntry

@EnableScan
public interface EventLogEntryRepository extends DynamoDBCrudRepository<EventLogEntry, String> {
  // ...
}

它总是告诉我:

com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: no key(s) present on class io.shido.events.domain.AdminEventLogEntry

一旦我(再次)宣布密钥,它就会工作:

@DynamoDBHashKey(attributeName = "EventId")
private String eventId;

所以我的问题是:我是否需要重新声明层次结构之间可能通用的所有字段?看起来它没有从父级识别HashKey

有线索吗?

我(不久前)找到了解决方案,所以我正在更新帖子,以备将来有人需要。请注意,abstract类已不存在,也许您可以出于自己的目的对其进行调整,那时我没有时间测试它(现在没有……所以它更简单,从OOP的角度来看可能不完全正确)。

问题出在类层次结构和(基于Spring的)AmazonDB客户端的配置上。接下来的类是实际的解决方案。

(a)AmazonDynamoDB客户端的Spring配置文件

请注意,您可能不需要dynamoDBOperationsRef,因为它仅在"每个环境"需要不同表的情况下使用。具有DynamoDB(如果你只有一个帐户)你不能有不同的"环境",所以你必须找到一种解决方法。这是解决方案:为表添加前缀(并将安全设置应用为必需)。

@Configuration
@EnableContextInstanceData // Only if you are going to use Identity and Access Management (IAM)
@EnableDynamoDBRepositories(basePackages = "io.shido.events", dynamoDBOperationsRef = "dynamoDBOperations")
class AmazonConfiguration {
  @Value("${aws.endpoint.dynamodb}")
  private String dynamoDbEndpoint;
  @Value("${ENV:local}")
  private String environment;
  @Bean
  public AmazonDynamoDB amazonDynamoDB() {
    final AmazonDynamoDBClient client = new AmazonDynamoDBClient();
    //client.setSignerRegionOverride(Regions.fromName(region).getName());
    if (StringUtils.isNotEmpty(dynamoDbEndpoint)) {
      client.setEndpoint(dynamoDbEndpoint);
    }
    return client;
  }
  @Bean
  public DynamoDBOperations dynamoDBOperations() {
    final DynamoDBTemplate template = new DynamoDBTemplate(amazonDynamoDB());
    final DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder()
      .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(environment + "-"))
      .build();
    template.setDynamoDBMapperConfig(mapperConfig);
    return template;
  }
}

(b)DynamoDB注释的"实体"类

package io.shido.events;
// imports
@DynamoDBTable(tableName = "EventLogs")
final class EventLogEntry implements Serializable {
  // Define your own long serialVersionUID
  @DynamoDBHashKey(attributeName = "EventId")
  private String eventId;
  @DynamoDBTypeConvertedEnum
  @DynamoDBAttribute(attributeName = "EventType")
  private EventType type;
  @DynamoDBAttribute(attributeName = "EntityId")
  private String entityId;
  @Scrambled
  @DynamoDBAttribute(attributeName = "Event")
  private Event event;
  @DynamoDBAttribute(attributeName = "GeneratedAt")
  @DynamoDBTypeConverted(converter = ZonedDateTimeConverter.class)
  private ZonedDateTime generatedAt;
  public EventLogEntry() {
    generatedAt = ZonedDateTime.now();
  }
  public EventLogEntry(AdminEvent event) {
    this();
    eventId = event.getId();
    type = EventType.ADMIN;
    entityId = event.getEntityId();
    this.event = event;
  }
  public EventLogEntry(UserEvent event) {
    this();
    eventId = event.getId();
    type = EventType.USER;
    entityId = event.getEntityId();
    this.event = event;
  }
  // getters and setters (a MUST, at least till the version I'm using)
  // hashCode(), equals and toString()
}

(c)Spring存储库定义

@EnableScan
public interface EventLogEntryRepository extends DynamoDBCrudRepository<EventLogEntry, String> { }

(d)表格定义

最终,你定义属性的方式这取决于您和/或您的要求。

{
  "TableName" : "local-EventLogs",
  "AttributeDefinitions" : [
    { "AttributeName" : "EventId", "AttributeType" : "S" },
    { "AttributeName" : "EventType", "AttributeType" : "S" },
    { "AttributeName" : "EntityId", "AttributeType" : "S" },
    { "AttributeName" : "Event", "AttributeType" : "S" },
    { "AttributeName" : "GeneratedAt", "AttributeType" : "S" }
  ],
  "KeySchema" : [ { "AttributeName" : "EventId", "KeyType" : "HASH" } ],
  "ProvisionedThroughput" : { "ReadCapacityUnits" : 10, "WriteCapacityUnits" : 10 }
}

相关内容

  • 没有找到相关文章

最新更新