

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 他のクラスの属性をフラット化する
<a name="ddb-en-client-adv-features-flatmap"></a>

テーブルの属性が継承または構成によって複数の異なる Java クラスに分散している場合、DynamoDB Enhanced Client API では属性を 1 つのクラスにフラット化するためのサポートを提供します。

## 継承を使用する
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

クラスで継承を使用する場合は、以下の方法で階層をフラット化してください。

### 注釈の付いた Bean を使用する
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

注釈手法では、両方のクラスに `@DynamoDbBean` 注釈が必要で、1 つのクラスに 1 つ以上のプライマリキーの注釈を付ける必要があります。

継承関係を持つデータクラスの例を以下に示します。

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

@DynamoDbBean
public abstract class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

Lombok [`onMethod` のオプション](https://projectlombok.org/features/experimental/onX)では、`@DynamoDbPartitionKey` などの属性ベースの DynamoDB 注釈が生成コードにコピーされます。

```
@DynamoDbBean
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord {
    private String name;
}

@Data
@DynamoDbBean
public abstract class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

### 静的スキーマを使用する
<a name="ddb-en-client-adv-features-flatmap-inheritance-static"></a>

静的スキーマアプローチでは、ビルダーの `extend()` メソッドを使用して親クラスの属性を子クラスに集約します。これは次の例のコメント行 1 の後で示されています。

```
        StaticTableSchema<org.example.tests.model.inheritance.stat.GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.GenericRecord.class)
                        // The partition key will be inherited by the top level mapper.
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getId)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(org.example.tests.model.inheritance.stat.GenericRecord::getCreatedDate)
                                .setter(org.example.tests.model.inheritance.stat.GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<org.example.tests.model.inheritance.stat.Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(org.example.tests.model.inheritance.stat.Customer.class)
                        .newItemSupplier(org.example.tests.model.inheritance.stat.Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(org.example.tests.model.inheritance.stat.Customer::getName)
                                .setter(org.example.tests.model.inheritance.stat.Customer::setName))
                        // 1. Use the extend() method to collapse the parent attributes onto the child class.
                        .extend(GENERIC_RECORD_SCHEMA)     // All the attributes of the GenericRecord schema are added to Customer.
                        .build();
```

先ほどの静的スキーマの例では、次のデータクラスを使用しています。マッピングは静的テーブルスキーマの構築時に定義されるため、データクラスには注釈は必要ありません。

#### データクラス
<a name="gunk"></a>

------
#### [ Standard data class ]

```
public class Customer extends GenericRecord {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}


public abstract class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
```

------
#### [ Lombok ]

```
@Data
@ToString(callSuper = true)
public class Customer extends GenericRecord{
    private String name;
}

@Data
public abstract class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

## 構成を使用する
<a name="ddb-en-client-adv-features-flatmap-comp"></a>

クラスで構成を使用する場合は、以下の方法で階層をフラット化してください。

### 注釈の付いた Bean を使用する
<a name="ddb-en-client-adv-features-flatmap-comp-anno"></a>

`@DynamoDbFlatten` 注釈は格納されているクラスをフラット化します。

以下のデータクラスの例では、`@DynamoDbFlatten` 注釈を使用して、含まれている `GenericRecord` クラスのすべての属性を `Customer` クラスに効果的に追加しています。

------
#### [ Standard data class ]

```
@DynamoDbBean
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    @DynamoDbFlatten
    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

@DynamoDbBean
public class GenericRecord {
    private String id;
    private String createdDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
@DynamoDbBean
public class Customer {
    private String name;
    @Getter(onMethod_=@DynamoDbFlatten)
    private GenericRecord record;
}

@Data
@DynamoDbBean
public class GenericRecord {
    @Getter(onMethod_=@DynamoDbPartitionKey)
    private String id;
    private String createdDate;
}
```

------

フラット化された注釈を使用すると、対象となるさまざまなクラスを必要なだけフラット化できます。以下の制約が適用されます。
+ フラット化の後は、すべての属性名が一意でなければなりません。
+ パーティションキー、ソートキー、またはテーブル名は複数あってはなりません。

### 静的スキーマを使用する
<a name="ddb-en-client-adv-features-flatmap-comp-static"></a>

静的テーブルスキーマを構築するときは、ビルダーの `flatten()` メソッドを使用します。また、含まれているクラスを識別する getter メソッド と setter メソッドも指定します。

```
        StaticTableSchema<GenericRecord> GENERIC_RECORD_SCHEMA =
                StaticTableSchema.builder(GenericRecord.class)
                        .newItemSupplier(GenericRecord::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(GenericRecord::getId)
                                .setter(GenericRecord::setId)
                                .tags(primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("created_date")
                                .getter(GenericRecord::getCreatedDate)
                                .setter(GenericRecord::setCreatedDate))
                        .build();

        StaticTableSchema<Customer> CUSTOMER_SCHEMA =
                StaticTableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getName)
                                .setter(Customer::setName))
                        // Because we are flattening a component object, we supply a getter and setter so the
                        // mapper knows how to access it.
                        .flatten(GENERIC_RECORD_SCHEMA, Customer::getRecord, Customer::setRecord)
                        .build();
```

先ほどの静的スキーマの例では、次のデータクラスを使用しています。

#### データクラス
<a name="ddb-en-client-adv-features-flatmap-comp-static-supporting"></a>

------
#### [ Standard data class ]

```
public class Customer {
    private String name;
    private GenericRecord record;

    public String getName() { return this.name; }
    public void setName(String name) { this.name = name; }

    public GenericRecord getRecord() { return this.record; }
    public void setRecord(GenericRecord record) { this.record = record; }

public class GenericRecord {
    private String id;
    private String createdDate;

    public String getId() { return this.id; }
    public void setId(String id) { this.id = id; }

    public String getCreatedDate() { return this.createdDate; }
    public void setCreatedDate(String createdDate) { this.createdDate = createdDate; }
}
```

------
#### [ Lombok ]

```
@Data
public class Customer {
    private String name;
    private GenericRecord record;
}

@Data
public class GenericRecord {
    private String id;
    private String createdDate;
}
```

------

ビルダーパターンを使用して、対象となるさまざまなクラスを必要なだけフラット化できます。

## 他のコードへの影響
<a name="ddb-en-client-adv-features-flatmap-compare"></a>

`@DynamoDbFlatten` 属性 (または `flatten()` ビルダーメソッド) を使用する場合、DynamoDB の項目には、構成オブジェクトの各属性の属性が含まれます。また、構成オブジェクトの属性も含まれます。

これとは対照的に、データクラスに構成クラスの注釈を付け、`@DynamoDbFlatten` を使用しない場合、その項目は構成オブジェクトとともに単一の属性として保存されます。

たとえば、[構成例によるフラット化](#ddb-en-client-adv-features-flatmap-comp-anno)で示された `Customer` クラスを、`record` 属性をフラット化する場合とフラット化しない場合で比較します。次の表に示すように、JSON との違いを視覚化できます。


****  

| フラット化あり | フラット化なし | 
| --- | --- | 
| 3 つの属性 | 2 つの属性 | 
|  <pre>{<br />  "id": "1",<br />  "createdDate": "today",<br />  "name": "my name"<br />}</pre>  |  <pre>{<br />  "id": "1",<br />  "record": {<br />      "createdDate": "today",<br />      "name": "my name"<br />  }<br />}</pre>  | 

他のコードが DynamoDB テーブルにアクセスしていて、特定の属性を見つけることを想定している場合には、この違いが重要になります。