我正在使用这个库与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);
}
}
典型的类层次结构。现在我正在尝试使用一个公共存储库来存储AdminEventLogEntry
和UserEventLogEntry
@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 }
}