2016-08-01 17 views
2

私は、thisライブラリを使用して、SpringブートとAmazon DynamoDBで作業しています。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 */ 
} 

...他1:

public class AdminEventLogEntry extends EventLogEntry { 
    private static final long serialVersionUID = 1953428576998278984L; 

    public AdminEventLogEntry(AdminEvent event) { 
    super(event); 
    } 
} 

...そして最後の1:

問題は、このクラス階層であります
public class UserEventLogEntry extends EventLogEntry { 
    private static final long serialVersionUID = 6845335344191463717L; 

    public UserEventLogEntry(UserEvent event) { 
    super(event); 
    } 
} 

典型的なクラス階層です。それが動作するキー

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

とすぐに私は(再び)を宣言として:今、私は、共通リポジトリ使っAdminEventLogEntryUserEventLogEntryを保存しようとしている:

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

を...そしてそれは常に私に語りました:

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

私の質問は次のとおりです。階層間で共通する可能性のあるすべてのフィールドを再宣言する必要がありますか?親からのHashKeyを認識していないようです。

手がかりはありますか?

+0

この解決策をお探しですか? –

+0

はい!そして、それはかなり素晴らしい(今のところ)ように働いています。私はそれを投稿します。 –

答えて

1

私は解決策を見つけました(しばらく前)ので、誰かが将来的にそれを必要とする場合に備えて投稿を更新しています。 abstractクラスが存在しなくなったことに気づいてください。あなた自身の目的のために調整することができます。それでテストする時間がありませんでした(今はそうではありません...より簡単です。

問題は、クラス階層と(Springベースの)AmazonDBクライアントの設定にありました。次のクラスは実際の解決策です。

(a)Amazon DynamoDBクライアント用のSpring設定ファイル。

それだけであなたが「環境ごとに」別のテーブルを必要とする場合に使用 ですので、あなたがdynamoDBOperationsRefを必要としない場合があります注意してください。 DynamoDB(アカウントが1つだけの場合)では、異なる 「環境」を持つことはできませんので、回避策を見つける必要があります。これは 解決策です:テーブルにプレフィックスを付ける(セキュリティ設定は が必要です)。

@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 } 
}