AWS DynamoDB:无法取消转换属性错误
Posted
技术标签:
【中文标题】AWS DynamoDB:无法取消转换属性错误【英文标题】:AWS DynamoDB: Could not unconvert attribute error 【发布时间】:2018-06-04 05:43:21 【问题描述】:我有问题,我无法处理。例如,我在 KitchenService 中创建了 CRUD 方法。我有 addProduct 等方法,这些方法很好。但是我有 Recipe 类,我正在使用 Product 类字段。在这种情况下,我遇到了很大的问题。
我的 addRecipe 方法:
public Recipe addRecipe (Recipe recipe)
List<RecipeElement> recipeElements = recipe.getRecipeElements();
for (RecipeElement recipeElement : recipeElements)
String id = recipeElement.getProduct().getId();
Product product = databaseController.get(Product.class, id);
recipeElement.setProduct(product);
databaseController.saveRecipe(recipe);
logger.log("Recipe created");
return recipe;
构建成功,所以我想在 POSTMAN 中对其进行测试,这就是我发送的 JSON 女巫的外观:
"id":null,"name":"test3","labels":["GLUTEN_FREE"],"author":"name":"Plejer Annołn","id":"testID2","media":"name":"heheszki","url":"http://blabla.pl","mediaType":"IMAGE","recipeElements":["product":"id":"ecacaf36-29a2-41c6-942e-be5a715ed094","weight":"100"],"approved":false
然后我收到“消息”:“内部服务器错误”,所以我正在检查日志,这就是我在那里发现的:
Product[Media]; could not unconvert attribute: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException
Caused by: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException: could not invoke public void pl.javamill.model.kitchen.Product.setMedia(pl.javamill.model.common.Media) on class pl.kitchen.Product with value name=heheszki, url=http://blabla.pl, mediaType=IMAGE of type class java.util.LinkedHashMap
Recipe Class 是这样的:
@DynamoDBTable(tableName = "recipe")
public class Recipe extends Request
/**
* Id of kitchen content
*/
private String id;
/**
* Name of recipe
*/
private String name;
/**
* Labels of product for example gluten fee product
*/
private List<KitchenLabel> labels;
/**
* Author of content.
*/
private Author author;
/**
* Address of content image.
*/
private Media media;
private Boolean approved;
private List<RecipeElement> recipeElements;
@DynamoDBHashKey(attributeName = "id")
@DynamoDBAutoGeneratedKey
public String getId()
return id;
public void setId(String id)
this.id = id;
@DynamoDBAttribute(attributeName = "Name")
public String getName()
return name;
public void setName(String name)
this.name = name;
@DynamoDBTypeConverted(converter = EnumConverter.class)
@DynamoDBAttribute(attributeName = "Labels")
public List<KitchenLabel> getLabels()
return labels;
public void setLabels(List<KitchenLabel> labels)
this.labels = labels;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Author")
public Author getAuthor()
return author;
public void setAuthor(Author author)
this.author = author;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Media")
public Media getMedia()
return media;
public void setMedia(Media media)
this.media = media;
@DynamoDBAttribute(attributeName = "Approved")
public Boolean getApproved()
return approved;
public void setApproved(Boolean approved)
this.approved = approved;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "RecipeElements")
public List<RecipeElement> getRecipeElements()
return recipeElements;
public void setRecipeElements(List<RecipeElement> recipeElements)
this.recipeElements = recipeElements;
RecipeElement 类:
public class RecipeElement
private Product product;
private Integer weight;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBHashKey(attributeName = "product")
public Product getProduct()
return product;
public void setProduct(Product product)
this.product = product;
public Integer getWeight()
return weight;
public void setWeight(Integer weight)
this.weight = weight;
和产品类:
@DynamoDBTable(tableName = "product")
public class Product extends Request
/**
* Id of kitchen content
*/
private String id;
/**
* Name of product
*/
private String name;
/**
* Calories in 100g
*/
private Integer calories;
/**
* Fat in 100g
*/
private Double fat;
/**
* Total carbo in 100g
*/
private Double carbo;
/**
* Total Protein in 100g
*/
private Double protein;
/**
* Labels of product for example gluten fee product
*/
private List<ProductKind> productKinds;
/**
* Author of content.
*/
private Author author;
/**
* Address of content image.
*/
private Media media;
private Boolean approved;
@DynamoDBHashKey(attributeName = "id")
@DynamoDBAutoGeneratedKey
public String getId()
return id;
public void setId(String id)
this.id = id;
@DynamoDBAttribute(attributeName = "Name")
public String getName()
return name;
public void setName(String name)
this.name = name;
@DynamoDBAttribute(attributeName = "Calories")
public Integer getCalories()
return calories;
public void setCalories(Integer calories)
this.calories = calories;
@DynamoDBAttribute(attributeName = "Fat")
public Double getFat()
return fat;
public void setFat(Double fat)
this.fat = fat;
@DynamoDBAttribute(attributeName = "Carbo")
public Double getCarbo()
return carbo;
public void setCarbo(Double carbo)
this.carbo = carbo;
@DynamoDBAttribute(attributeName = "Protein")
public Double getProtein()
return protein;
public void setProtein(Double protein)
this.protein = protein;
@DynamoDBTypeConverted(converter = EnumConverter.class)
@DynamoDBAttribute(attributeName = "ProductKinds")
public List<ProductKind> getProductKinds()
return productKinds;
public void setProductKinds(List<ProductKind> productKinds)
this.productKinds = productKinds;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Author")
public Author getAuthor()
return author;
public void setAuthor(Author author)
this.author = author;
@DynamoDBTypeConverted(converter = ObjectConverter.class)
@DynamoDBAttribute(attributeName = "Media")
public Media getMedia()
return media;
public void setMedia(Media media)
this.media = media;
@DynamoDBAttribute(attributeName = "Approved")
public Boolean getApproved()
return approved;
public void setApproved(Boolean approved)
this.approved = approved;
这是我的转换器类:
public class ObjectConverter<T extends Object>
implements DynamoDBTypeConverter<String, T>
ObjectMapper objectMapper = new ObjectMapper();
@Override
public String convert(T object)
try
return objectMapper.writeValueAsString(object);
catch (JsonProcessingException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
throw new IllegalArgumentException("Unable to parse JSON");
@Override
public T unconvert(String object)
try
T unconvertedObject = objectMapper.readValue(object,
new TypeReference<T>()
);
return unconvertedObject;
catch (IOException e)
e.printStackTrace();
return null;
有人可以帮我解决这个问题吗?
【问题讨论】:
这个问题你解决了吗?我现在遇到了。谢谢! 【参考方案1】:简答:
向 Media 类添加一个公共的空构造函数。
长答案:
在您的代码中,当您执行databaseController.get(Product.class, id)
时,您正在调用DynamoDBMapperTableModel 的下划线方法public T unconvert(final Map<String,AttributeValue> object)
:
@Override
public T unconvert(final Map<String,AttributeValue> object)
final T result = StandardBeanProperties.DeclaringReflect.<T>newInstance(targetType);
if (!object.isEmpty())
for (final DynamoDBMapperFieldModel<T,Object> field : fields())
try
final AttributeValue value = object.get(field.name());
if (value != null)
field.unconvertAndSet(result, value);
catch (final RuntimeException e)
throw new DynamoDBMappingException(
targetType.getSimpleName() + "[" + field.name() + "]; could not unconvert attribute", e
);
return result;
在此方法的第一行中,正在使用反射创建表模型的新实例(在您的情况下是 Product
的新实例),然后将新实例的字段转换为所需的类和相应地设置。
StandardBeanProperties.DeclaringReflect.<T>newInstance(targetType)
在targetType
上调用.newInstance()
,它的类型是Class<T>
。
如Class.newInstance() documentation 中所写,如果类没有空构造函数,则抛出InstantiationException
。还有其他情况会引发此异常,但根据我的经验,这可能是因为未实现公共的空构造函数。
【讨论】:
【参考方案2】:对我来说,这是 setter 方法中的拼写错误。
@DynamoDBAttribute(attributeName = "closed_date_time")
public Date getClosedDateTime()
return closedDateTime;
public void setClosedDate(Date closedDateTime)
this.closedDateTime = closedDateTime;
我已将 setClosedDate
替换为 setClosedDateTime
,然后它起作用了。
【讨论】:
【参考方案3】:再次生成 Setter Getter 就可以了! 在我的情况下也是一个错字。
但是如果列的 DataType 是 Long 并且您将 dataType 转换为 String。这也可能导致现有数据出现此问题。
【讨论】:
这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review 这并不能真正回答问题。如果您有其他问题,可以点击 提问。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 - From Review以上是关于AWS DynamoDB:无法取消转换属性错误的主要内容,如果未能解决你的问题,请参考以下文章
类 java.lang.String 在 DynamoDB 创建表时无法转换为 Long
DynamoDB 无法转换为 System.DateTime