web-dev-qa-db-fra.com

JAVA DynamoDB: non pris en charge; nécessite @DynamoDBTyped ou @DynamoDBTypeConverted

J'ai créé des méthodes CRUD mais j'ai quelques problèmes avec ça.

Voici mon code de méthode d'ajout:

public Product addProduct(Product content) {
    Product item = new Product();

    item.setName(content.getName());
    item.setCalories(content.getCalories());
    item.setFat(content.getFat());
    item.setCarbo(content.getCarbo());
    item.setProtein(content.getProtein());
    item.setProductKinds(content.getProductKinds());
    item.setAuthor(content.getAuthor());
    item.setMedia(content.getMedia());
    item.setApproved(content.getApproved());


    databaseController.saveTest(item);
    logger.log("Item created");


    return item;
}

Voici ma méthode editProduct:

public Product editProduct(Product product) {
    Product databaseProduct = databaseController.get(Product.class, product.getId());
    databaseProduct.setAllProducts(product);
    databaseController.save(databaseProduct);
    return databaseProduct;
}

En classe modèle, je pense avoir tout bien fait:

package pl.javamill.model.kitchen;

import com.amazonaws.services.dynamodbv2.datamodeling.*;
import pl.javamill.model.Request;
import pl.javamill.model.common.Author;
import pl.javamill.model.common.AuthorConverter;
import pl.javamill.model.common.Media;
import pl.javamill.model.common.MediaConverter;

import Java.util.List;

@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;
}

@DynamoDBTypeConvertedEnum
@DynamoDBTypeConverted(converter = ProductKindConverter.class)
@DynamoDBAttribute(attributeName = "ProductKinds")
public List<ProductKind> getProductKinds() {
    return productKinds;
}

public void setProductKinds(List<ProductKind> productKinds) {
    this.productKinds = productKinds;
}

@DynamoDBTypeConverted(converter = AuthorConverter.class)
@DynamoDBAttribute(attributeName = "Author")
public Author getAuthor() {
    return author;
}

public void setAuthor(Author author) {
    this.author = author;
}

@DynamoDBTypeConverted(converter = MediaConverter.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 void setAllProducts(Product product) {
    if (!getName().equals(product.getName())) {
        setName(product.getName());
    }
    if (!getCalories().equals(product.getCalories())) {
        setCalories(product.getCalories());
    }
    if (!getFat().equals(product.getFat())) {
        setFat(product.getFat());
    }
    if (!getCarbo().equals(product.getCarbo())) {
        setCarbo(product.getCarbo());
    }
    if (!getProtein().equals(product.getProtein())) {
        setProtein(product.getProtein());
    }
    if (!getProductKinds().equals(product.getProductKinds())) {
        setProductKinds(product.getProductKinds());
    }
    if (!getAuthor().equals(product.getAuthor())) {
        setAuthor(product.getAuthor());
    }
    if (!getMedia().equals(product.getMedia())) {
        setMedia(product.getMedia());
    }
    if (!getApproved().equals(product.getApproved())) {
        setApproved(product.getApproved());
    }

}


@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Product product = (Product) o;

    if (name != null ? !name.equals(product.name) : product.name != null) return false;
    if (calories != null ? !calories.equals(product.calories) : product.calories != null) return false;
    if (fat != null ? !fat.equals(product.fat) : product.fat != null) return false;
    if (carbo != null ? !carbo.equals(product.carbo) : product.carbo != null) return false;
    if (protein != null ? !protein.equals(product.protein) : product.protein != null) return false;
    if (productKinds != null ? !productKinds.equals(product.productKinds) : product.productKinds != null)
        return false;
    if (author != null ? !author.equals(product.author) : product.author != null) return false;
    if (media != null ? !media.equals(product.media) : product.media != null) return false;
    return approved != null ? approved.equals(product.approved) : product.approved == null;
}

@Override
public int hashCode() {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    result = 31 * result + (calories != null ? calories.hashCode() : 0);
    result = 31 * result + (fat != null ? fat.hashCode() : 0);
    result = 31 * result + (carbo != null ? carbo.hashCode() : 0);
    result = 31 * result + (protein != null ? protein.hashCode() : 0);
    result = 31 * result + (productKinds != null ? productKinds.hashCode() : 0);
    result = 31 * result + (author != null ? author.hashCode() : 0);
    result = 31 * result + (media != null ? media.hashCode() : 0);
    result = 31 * result + (approved != null ? approved.hashCode() : 0);
    return result;
}

}

ProductKindConventor:

public class ProductKindConverter implements DynamoDBTypeConverter<String, List<ProductKind>> {

@Override
public String convert(List<ProductKind> objects) {
    //Jackson object mapper
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        String objectsString = objectMapper.writeValueAsString(objects);
        return objectsString;
    } catch (JsonProcessingException e) {
        //do something
    }
    return null;
}

@Override
public List<ProductKind> unconvert(String objectsString) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        List<ProductKind> objects = objectMapper.readValue(objectsString, new TypeReference<List<ProductKind>>(){});
        return objects;
    } catch (JsonParseException e) {
        //do something
    } catch (JsonMappingException e) {
        //do something
    } catch (IOException e) {
        //do something
    }
    return null;
}

}

Enregistrer la méthode dans dbcontroller:

public void saveTest(Product product){
    AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
            .withRegion(regions).build();
    mapper = new DynamoDBMapper(client);
    mapper.save(product);

}

Obtenez le produit de la méthode DB:

public Product getTest(String id) {
    AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
            .withRegion(regions).build();
    mapper = new DynamoDBMapper(client);
    Product retrivedProduct = mapper.load(Product.class, id);
    return retrivedProduct;
}

Le test unitaire a réussi, tout semble aller bien, mais lorsque j'utilisais POSTMAN pour tester, j'ai eu quelques erreurs. J'envoie un produit sous json et il semble que:

{"id": null, "name": "yoloornotyolo", "calories": 1000, "lipides": 400.0, "carbo": 20.0, "protein": 40.0, "productKinds": ["MEAT"], " auteur ": {" nom ":" Plejer Annołn "," id ":" testID2 "}," media ": {" nom ":" heheszki "," url ":" http: // blabla. pl "," mediaType ":" IMAGE "}," approuvé ": faux}

Ensuite, j'ai "" message ":" Erreur de serveur interne "", donc je vérifie le fichier journal et ce que je peux voir:

non supporté; nécessite @DynamoDBTyped ou @DynamoDBTypeConverted: com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException

Je ne sais pas ce qui ne va pas. Quelqu'un peut-il m'expliquer ce que je suppose faire?

7
D.Zet

Il serait utile de voir votre méthode saveProduct. Vous utilisez des annotations DynamoDBMapper mais il semble que vous essayez d'enregistrer un objet article, pas un objet produit. Plutôt que

Item item = new Item()

Utilisation

Product item = new Product();
item.setName...

Une chose que je mentionnerais est que vous pouvez décharger la gestion de votre identifiant généré vers DyanmoDBMapper en utilisant annotation DynamoDBAutoGeneratedKey

Dans votre classe modèle, procédez comme suit:

@DynamoDBHashKey(attributeName = "Id")
@DynamoDBAutoGeneratedKey
public String getId() { return id; }
public void setId(String id) { this.id = id; } 

Et puis vous n'avez pas besoin de gérer id dans votre méthode addProduct

EDIT: votre méthode saveProduct doit être dans le sens de

DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
mapper.save(item)

Je doute que vous ayez besoin de passer un nom de table car il s'agit d'une annotation sur votre objet Product. Vous ne devriez pas utiliser putItem.

EDIT: votre méthode saveProduct doit prendre un objet Product, pas un objet Item. N'utilisez pas putItem car cela ne connaît pas votre classe de modèle. Utilisez la fonction de sauvegarde de DynamoDBMapper. Vous n'avez pas besoin de spécifier le nom de la table car c'est une annotation sur votre classe de produit (la table est appelée "produit"). Vous devez utiliser AmazonDynamoDB pour l'interfaçage avec DynamoDB. La méthode ci-dessous return est nulle, vous devrez donc mettre à jour la méthode addProduct.

public void saveProduct(Product item) {

logger.log("Starting to save an item");

//You need a new method to return an AmazonDynamoDB interface 
AmazonDynamoDB dynamoDB = getAmazonDynamoDB();
DynamoDBMapper mapper = new DynamoDBMapper(dynamoDB);
mapper.save(item)

logger.log("Item stored");

return saved;
}

EDIT: vous créez une interface AmazonDynamoDB comme celle-ci

   // Set to your chosen region
   AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
   .withRegion(Regions.US_WEST_2)
   .build(); 

EDIT: DynamoDBMapper ne prend en charge que certains types de données .

Vous avez là trois types de données complexes; productKind, auteur et médias. Si vous souhaitez les stocker dans votre base de données, vous devrez écrire un Convertor Class pour chacun. La classe de convertisseur définit généralement la façon dont vous convertissez votre objet en chaîne et inversement.

EDIT: Votre ensemble, ProductKind, aura besoin d'un convertisseur qui ressemble à this . Remplacez simplement "MyObject" par ProductKinds.

5
F_SO_K

Il serait utile d'avoir une trace de pile pour l'exception. Dans le message intermédiaire, il contient le type de données et les informations de champ qui ne peuvent pas être convertis.

Habituellement, vous n'avez pas besoin de faire de convertisseurs, assurez-vous simplement d'avoir @DynamoDBDocument sur toutes les classes personnalisées et @DynamoDBTypeConvertedEnum sur toutes les énumérations personnalisées utilisées.

0
Volodymyr Zubariev