

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 扁平化其他類別的屬性
<a name="ddb-en-client-adv-features-flatmap"></a>

如果資料表的屬性分散在數個不同的 Java 類別，無論是透過繼承或合成，DynamoDB 增強型用戶端 API 都支援將屬性扁平化為一個類別。

## 使用繼承
<a name="ddb-en-client-adv-features-flatmap-inheritance"></a>

如果您的類別使用繼承，請使用下列方法來扁平化階層。

### 使用註釋的 Bean
<a name="ddb-en-client-adv-features-flatmap-inheritance-anno"></a>

對於註釋方法，兩個類別都必須帶有`@DynamoDbBean`註釋，而類別必須帶有一個或多個主索引鍵註釋。

以下顯示具有繼承關係的資料類別範例。

------
#### [ 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)會將屬性型 DynamoDB 註釋，例如 `@DynamoDbPartitionKey`，複製到產生的程式碼。

```
@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`，則項目會與編寫的物件一起儲存為單一屬性。

例如，比較平面化中顯示的`Customer`類別與合成範例，包含和不包含`record`屬性的平面化。 [使用註釋的 Bean](#ddb-en-client-adv-features-flatmap-comp-anno)您可以使用 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 資料表，差異就變得很重要。