2016-08-01 10 views
2

Я работаю с Spring Boot и Amazon DynamoDB с использованием библиотеки this. Проблема с этой иерархии классов: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 от родителя.

Любые подсказки?

+0

вы нашли решение для этого? –

+0

Да! И он работает довольно круто (до сих пор). Я отправлю его. –

ответ

1

Я нашел решение (некоторое время назад), поэтому я обновляю сообщение, если кому-то это понадобится в будущем. Обратите внимание, что класс abstract больше не существует, возможно, вы можете настроить его для своих целей, у меня не было времени на то, чтобы проверить его (а не сейчас ... так что это проще, возможно, не совсем правильно с точки зрения ООП).

Проблема связана с иерархией классов и конфигурацией клиента AmazonDB (на основе Spring). Следующим классом является фактическое решение.

(a) Конфигурационный файл Spring для клиента Amazon DynamoDB.

Обратите внимание, что вам, возможно, не потребуется 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; 
    } 
} 

(б) 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() 
} 

(с) Определение Спринг хранилище.

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

(г) стол (ы) определения.

В конце концов, как можно определить атрибуты и тому подобное, что это до вас и/или ваше требование (ы).

{ 
    "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 } 
}