2016-08-01 5 views
2

this 라이브러리를 사용하는 스프링 부트 및 Amazon DynamoDB와 함께 작업하고 있습니다. ...Amazon DynamoDB 및 클래스 계층

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 */ 
} 

다른 :

@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 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 클래스가 더 이상 존재하지 않음을 주목하십시오. 자신의 목적에 맞게 조정할 수 있습니다. 테스트하지 않아도됩니다. (지금은 아니므로 간단합니다. OOP 관점에서 완전히 정확하지 않을 수도 있습니다.)

문제는 클래스 계층 구조 및 (Spring 기반) AmazonDB 클라이언트의 구성에서 발생했습니다. 다음 클래스는 실제 솔루션입니다.

(a) 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; 
    } 
} 

의 (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 } 
}