확장 사용 - AWS SDK for Java 2.x

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

확장 사용

DynamoDB 향상된 클라이언트 API는 매핑 작업 이외의 기능을 제공하는 플러그인 확장을 지원합니다. 확장에는 두 개의 후크 메서드, beforeWrite()afterRead()가 있습니다. beforeWrite()는 쓰기 작업이 발생하기 전에 수정하고, afterRead() 메서드는 읽기 작업이 발생한 후에 결과를 수정합니다. 일부 작업(예: 항목 업데이트)은 쓰기와 읽기를 모두 수행하므로 두 후크 메서드가 모두 호출됩니다.

확장은 향상된 클라이언트 빌더에 지정된 순서대로 로드됩니다. 하나의 확장이 이전 확장에 의해 변환된 값에 대해 작동할 수 있으므로 로드 순서가 중요할 수 있습니다.

향상된 클라이언트 API는 extensions 패키지에 있는 플러그인 확장 세트와 함께 제공됩니다. 기본적으로 확장 클라이언트는 VersionedRecordExtensionAtomicCounterExtension를 로드합니다. 향상된 클라이언트 빌더로 기본 동작을 재정의하고 확장 프로그램을 로드할 수 있습니다. 기본 확장자를 원하지 않는 경우에는 none을 지정할 수도 있습니다.

자체 확장을 로드하는 경우 확장 클라이언트는 기본 확장을 로드하지 않습니다. 기본 확장 중 하나가 제공하는 동작을 원하는 경우 해당 확장을 확장 목록에 명시적으로 추가해야 합니다.

다음 예제에서는 verifyChecksumExtension의 이름을 따서 이름이 지정된 사용자 지정 확장이 VersionedRecordExtension 다음에 로드되며, 이 확장은 일반적으로 기본적으로 자체적으로 로드됩니다. 이 예제에서는 AtomicCounterExtension가 로드되지 않습니다.

DynamoDbEnhancedClientExtension versionedRecordExtension = VersionedRecordExtension.builder().build(); DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(dynamoDbClient) .extensions(versionedRecordExtension, verifyChecksumExtension) .build();

VersionedRecordExtension

VersionedRecordExtension는 기본적으로 로드되며 항목이 데이터베이스에 기록될 때 항목 버전 번호를 증가시키고 추적합니다. 실제 지속 항목의 버전 번호가 애플리케이션이 마지막으로 읽은 값과 일치하지 않는 경우 쓰기가 실패하도록 하는 조건이 모든 쓰기에 추가됩니다. 이 동작은 항목 업데이트에 대한 낙관적 잠금 기능을 효과적으로 제공합니다. 첫 번째 프로세스가 항목을 읽고 업데이트를 쓰는 사이에 다른 프로세스가 항목을 업데이트하면 쓰기가 실패합니다.

항목 버전 번호를 추적하는 데 사용할 속성을 지정하려면 테이블 스키마에서 숫자 속성에 태그를 지정하세요.

다음 코드 조각은 version 속성에 항목 버전 번호가 포함되도록 지정합니다.

@DynamoDbVersionAttribute public Integer getVersion() {...}; public void setVersion(Integer version) {...};

동일한 정적 테이블 스키마 접근 방식이 다음 코드 조각에 나와 있습니다.

.addAttribute(Integer.class, a -> a.name("version") .getter(Customer::getVersion) .setter(Customer::setVersion) // Apply the 'version' tag to the attribute. .tags(VersionedRecordExtension.AttributeTags.versionAttribute())

AtomicCounterExtension

AtomicCounterExtension는 기본적으로 로드되며 레코드가 데이터베이스에 기록될 때마다 태그가 지정된 숫자 속성이 증가합니다. 시작 및 증분 값을 지정할 수 있습니다. 값을 지정하지 않으면 시작 값은 0으로 설정되고 속성 값은 1씩 증가합니다.

어떤 속성이 카운터인지 지정하려면 테이블 스키마에서 Long 유형의 속성에 태그를 지정하세요.

다음 코드 조각은 counter 속성의 기본 시작 및 증분 값 사용을 보여줍니다.

@DynamoDbAtomicCounter public Long getCounter() {...}; public void setCounter(Long counter) {...};

정적 테이블 스키마 접근 방식이 다음 코드 조각에 나와 있습니다. 원자 카운터 확장은 시작 값 10을 사용하고 레코드가 기록될 때마다 값을 5씩 증가시킵니다.

.addAttribute(Integer.class, a -> a.name("counter") .getter(Customer::getCounter) .setter(Customer::setCounter) // Apply the 'atomicCounter' tag to the attribute with start and increment values. .tags(StaticAttributeTags.atomicCounter(10L, 5L))

AutoGeneratedTimestampRecordExtension

AutoGeneratedTimestampRecordExtension는 항목이 데이터베이스에 성공적으로 기록될 때마다 Instant 유형의 태그가 지정된 속성을 현재 타임스탬프로 자동 업데이트합니다.

이 확장은 기본적으로 로드되지 않습니다. 따라서 이 항목의 첫 번째 예에 표시된 대로 향상된 클라이언트를 빌드할 때 이를 사용자 지정 확장으로 지정해야 합니다.

현재 타임스탬프로 업데이트할 속성을 지정하려면 테이블 스키마에서 Instant 속성에 태그를 지정하세요.

lastUpdate 속성은 다음 코드 조각에서 확장 동작의 대상입니다. 속성이 Instant 유형이어야 한다는 요구 사항에 유의하세요.

@DynamoDbAutoGeneratedTimestampAttribute public Instant getLastUpdate() {...} public void setLastUpdate(Instant lastUpdate) {...}

동일한 정적 테이블 스키마 접근 방식이 다음 코드 조각에 나와 있습니다.

.addAttribute(Instant.class, a -> a.name("lastUpdate") .getter(Customer::getLastUpdate) .setter(Customer::setLastUpdate) // Applying the 'autoGeneratedTimestamp' tag to the attribute. .tags(AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute())

사용자 지정 확장

다음 사용자 지정 확장 클래스는 업데이트 표현식을 사용하는 beforeWrite() 메서드를 보여줍니다. 데이터베이스의 항목에 아직 registrationDate 속성이 없는 경우 주석 2줄 다음에 SetAction를 만들어 registrationDate 속성을 설정합니다. Customer 객체가 업데이트될 때마다 확장 프로그램은 registrationDate가 설정되어 있는지 확인합니다.

public final class CustomExtension implements DynamoDbEnhancedClientExtension { // 1. In a custom extension, use an UpdateExpression to define what action to take before // an item is updated. @Override public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) { if ( context.operationContext().tableName().equals("Customer") && context.operationName().equals(OperationName.UPDATE_ITEM)) { return WriteModification.builder() .updateExpression(createUpdateExpression()) .build(); } return WriteModification.builder().build(); // Return an "empty" WriteModification instance if the extension should not be applied. // In this case, if the code is not updating an item on the Customer table. } private static UpdateExpression createUpdateExpression() { // 2. Use a SetAction, a subclass of UpdateAction, to provide the values in the update. SetAction setAction = SetAction.builder() .path("registrationDate") .value("if_not_exists(registrationDate, :regValue)") .putExpressionValue(":regValue", AttributeValue.fromS(Instant.now().toString())) .build(); // 3. Build the UpdateExpression with one or more UpdateAction. return UpdateExpression.builder() .addAction(setAction) .build(); } }