2017-02-09 5 views
0

J'utilise le datastax cassandra 3.1.2. J'ai créé le tableau suivant dans Cassandra et inséré un enregistrement.Cassandra Accessor/Mapper ne mappant pas le champ udt

CREATE TYPE memory (capacity text); 
create TABLE laptop (id uuid primary key, model text, ram frozen<memory>); 
select * from laptop ; 

id         | model   | ram 
--------------------------------------+---------------+------------------- 
e55cba2b-0847-40d5-ad56-ae97e793dc3e | Dell Latitude | {capacity: '8gb'} 

Quand je suis en train de chercher le champ de la capacité de mémoire de type congelé en Java en utilisant Cassandra accesseur avec le code ci-dessous:

this.cluster = Cluster.builder().addContactPoint(node).withPort(port).build(); 
session = cluster.connect(); 
MappingManager manager = new MappingManager(session); 
LaptopAccessor laptopAccessor = manager.createAccessor(LaptopAccessor.class); 
Result<Laptop> cp = laptopAccessor.getOne(UUID.fromString("e55cba2b-0847-40d5-ad56-ae97e793dc3e")); 
System.out.println(cp.one()); 

Il donne lui-même ram est nul du point de données. Je m'attendais à ce que le mappeur crée une instance de mémoire vive lors du mappage et de mapper le champ de capacité dans celui-ci et renvoyer le bean Laptop.

J'ai l'interface accesseur suivante:

@Accessor 
interface LaptopAccessor { 
    @Query("SELECT ram.capacity FROM user_info.laptop where id=?") 
    Result<Laptop> getOne(UUID id); 
} 

je les haricots java suivants pour le tableau ci-dessus.

@Table(keyspace = "user_info", name = "laptop") 
public class Laptop { 

    private UUID id; 
    private String model; 
    private Memory ram; 

    @PartitionKey 
    public UUID getId() { 
     return id; 
    } 

    public void setId(UUID id) { 
     this.id = id; 
    } 


    public String getModel() { 
     return model; 
    } 


    public void setModel(String model) { 
     this.model = model; 
    } 

    @Frozen 
    public Memory getRam() { 
     return ram; 
    } 


    public void setRam(Memory ram) { 
     this.ram = ram; 
    } 

    @Override 
    public String toString() { 
     return "id = " + id + " model = " + model + " ram = " + ram; 
    } 

} 

@UDT(keyspace = "user_info", name = "memory") 
public class Memory { 

    private String capacity; 

    @Field 
    public String getCapacity() { 
     return capacity; 
    } 


    public void setCapacity(String capacity) { 
     this.capacity = capacity; 
    } 

    @Override 
    public String toString() { 
     return "capacity = " + capacity ; 
    } 

} 

Le code fonctionne correctement lorsque je modifie la requête pour récupérer l'intégralité de la RAM UDT. Est-ce que quelqu'un pourrait dire pourquoi le mappeur ne fonctionne pas quand je sélectionne un champ de l'udt dans la requête?

Est-ce que cassandra ne supporte pas cela? Une solution de contournement pour récupérer les champs UDT?

Répondre

1

Je pense que la question est le type de retour sur votre accesseur:

@Accessor 
interface LaptopAccessor { 
    @Query("SELECT ram.capacity FROM user_info.laptop where id=?") 
    Result<Laptop> getOne(UUID id); 
} 

Étant donné que votre requête sélectionne uniquement ram.capacity, tout le conducteur est en train de revenir est une ligne avec une seule colonne qui est un String avec nom de ram.capacity qui ne correspond à aucun champ dans Laptop.

Au lieu de cela, car il ressemble à tout ce que vous voulez est la ligne 1 correspondant à cette requête, vous pouvez changer votre Accessor à:

@Accessor 
interface LaptopAccessor { 
    @Query("SELECT ram.capacity FROM user_info.laptop where id=?") 
    ResultSet getOne(UUID id); 
} 

L'accesseur retourne maintenant un ResultSet pour lequel vous pouvez appeler one().getString(0) pour obtenir le la capacité de retour. Ce n'est pas idéal si vous ne voulez pas traiter directement avec ResultSet, mais cela fonctionne bien.

Vous ne devriez pas vraiment besoin de tout l'objet Laptop de toute façon puisque tout ce que vous demandez est un champ d'un droit UDT?

+0

Merci pour la réponse, cependant, mes types de retour Accessor sont génériques et j'ai d'autres requêtes dans l'interface qui retourne l'objet Laptop complet et à travers ma partie fetcher (qui est async). Je collectionne toujours comme Collection results = results.add (future.get(). One()); Donc, je pense que travailler directement sur ResultSet ne fonctionnerait pas dans mon cas, surtout si j'ai plusieurs requêtes de ce type pour retourner uniquement les champs UDT qui ont une variété de types de données. – Ravi

+0

Je prévois de déplacer tous ces champs (que je veux récupérer depuis udt) au niveau de la table ou définir un espace réservé au niveau table (capacité) afin que je puisse déclencher une requête comme 'SELECT ram.capacity comme capacité FROM user_info.laptop où id =? ' – Ravi

+0

Si j'ai la structure de table suivante: CREATE TABLE user_info.employees_with_address ( id uuid PRIMARY KEY, complete_address liste >) Si j'obtiens complete_address en utilisant une requête simple, je dois faire quelque chose comme ci-dessous pour analyser la liste UDT Frozen UDT. Ligne r = rsf.get(). One(); r.getList (r.getColumnDefinitions(). GetName(), CompleteAddress.class); Si je veux le rendre générique, alors comment puis-je récupérer le type CompleteAddress.class en utilisant Définition? – Ravi