在DynamoDB中存储Java枚举的字符串值而不是枚举值本身

4

我正在使用DynamoDB,希望能够将enumString值存储而不是enum本身。

例如,我有如下enum

public enum Source {
  BREACH("breach"),
  LEAKAGE("leakage");

  private final String desc;

  Source(String desc) { this.desc = desc; }

  public String desc() { return desc; }
}

... 还有这个 "entity":

@DynamoDBTable(tableName = "Alerts")
public final class Alert implements Serializable {
  private static final long serialVersionUID = 4012517315640518044L;

  @DynamoDBHashKey(attributeName = "AlertId") // Partition Key or Hash Attribute
  private String alertId;

  @DynamoDBTypeConvertedEnum
  @DynamoDBAttribute(attributeName = "Source")
  private Source type;

  // Constructor(s), Getter(s), Setter(s), ToString, etc...
}

使用@DynamoDBTypeConvertedEnum注释,保存的值为BREACH,但我希望使用breach
{
  "AlertId": { "S": "a083168d-cb23-4ec8-ab80-a1c16955c4b8" },
  "Source": { "S": "BREACH" },
  ...
  "CreatedAt": { "S": "2017-05-03T14:07:36.395Z" }
}

有什么线索吗?我曾尝试“转换器”(不是所有的,虽然我无法让它工作),但我认为我最终得为每个enum类型都做一个转换器,因为它们都不同。

3个回答

1
你可以像这样编写Alert类,即将属性定义为字符串,并设计getter和setter以发送/接收枚举对象(即Source)。
Alert类:
    @DynamoDBTable(tableName = "Alerts")
public final class Alert implements Serializable {
    private static final long serialVersionUID = 4012517315640518044L;

    private String alertId;

    private String type;

    @DynamoDBHashKey(attributeName = "AlertId") 
    public String getAlertId() {
        return alertId;
    }

    @DynamoDBAttribute(attributeName = "Source")
    public Source getType() {
      if (type != null)
        return Source.valueOf(type);
      else
        return null;
    }

    public void setAlertId(String alertId) {
        this.alertId = alertId;
    }

    public void setType(Source type) {
        this.type = type.desc();
    }
}

创建警报:

将值存储在数据库表中,预期效果正常。从DynamoDB表中获取项目也可以正常工作。

public Boolean createAlert(String alertId, Source source) {
    DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(dynamoDBClient);
    Alert alert = new Alert();
    alert.setAlertId(alertId);
    alert.setType(source);
    dynamoDBMapper.save(alert);

    return true;

}

我也尝试过这种方法;但是当在持久化之前该值为 null 时,这种方法存在问题。当它尝试从 DynamoDB 中“查找”实体时,它会失败。有时 source 可能存在,也可能不存在。如果该值始终存在,则没有问题,但对于我来说并非如此。 - x80486
getType方法的最新更新应该处理源表中不存在的情况。DynamoDB获取应该正常工作,并且对象应该被正确反序列化。 - notionquest
是的!我明白了,但我正在寻找不同的东西:一个自定义注释或类似的东西。我不想处理那些“null”值;我宁愿使用内置的@DynamoDBTypeConvertedEnum。无论如何,谢谢! - x80486
我也遇到了同样的问题。有人能够解决 DynamoDB 的这个问题吗?即使是 @notionquest 和 sam 给出的解决方案也不起作用。 - Freephone Panwal

0

重写 toString() 方法,这应该可以工作。

public enum Source {

  BREACH("breach"),
  LEAKAGE("leakage");

  private final String desc;

  Source(String desc) { this.desc = desc; }

  public String desc() { return desc; }

  @Override
  public String toString() { return desc; }
}

0

我通过定义自定义属性转换器来解决了这个问题。它可以工作,但我担心您需要为每个枚举编写转换器。

已经有一个用于序列化desc()的方法。我们可以为反序列化toSource()定义一个静态方法Source.java

public enum Source {
    BREACH("breach"),
    LEAKAGE("leakage");

    private final String desc;

    Source(String desc) {
        this.desc = desc;
    }

    public String desc() {
        return desc;
    }

    public static Source toSource(String value) {
        return Arrays.stream(Source.values()).filter(et -> et.desc().equals(value)).findFirst().orElse(null);
    }
}

我们可以定义一个自定义的 DynamoDBType 转换器:

SourceEnumDynamoDbConverter.java

public class SourceEnumDynamoDbConverter implements DynamoDBTypeConverter<String, Source> {
    @Override
    public String convert(Source source) {
        return source.desc();
    }

    @Override
    public Source unconvert(String sourceStr) {
        return Source.toSource(sourceStr);
    }
}

最后,使用此自定义转换器注释我们实体的Source属性 Alert.java
@DynamoDBTable(tableName = "Alerts")
public final class Alert implements Serializable {
    private static final long serialVersionUID = 4012517315640518044L;

    @DynamoDBHashKey(attributeName = "AlertId") // Partition Key or Hash Attribute
    private String alertId;

    private Source type;

    @DynamoDBTypeConverted(converter = TrialEnumDynamoDbConverter.class)
    @DynamoDBAttribute(attributeName = "Source")
    public Source getSource() {
        return type;
    }

    public void setSource(Source type) {
        this.type = type;
    }

    // Constructor(s), Getter(s), Setter(s), ToString, etc...
}

这样desc被存储并从dynamodb中读取,结果为

{
  "AlertId": { "S": "a083168d-cb23-4ec8-ab80-a1c16955c4b8" },
  "Source": { "S": "breach" },
  ...
  "CreatedAt": { "S": "2017-05-03T14:07:36.395Z" }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接