web-dev-qa-db-fra.com

Lorsque vous créez un POJO dans Firebase, pouvez-vous utiliser ServerValue.TIMESTAMP?

Lorsque vous créez un ancien objet Java ordinaire destiné à être sérialisé et désérialisé vers Firebase, existe-t-il un moyen d'utiliser la valeur ServerValue.TIMESTAMP?

Par exemple, supposons que je souhaite avoir un objet dont l’une des propriétés est la dernière fois qu’elle a été modifiée et que vous souhaitez utiliser la valeur ServerValue.TIMESTAMP.

Dans la classe POJO, vous pourriez avoir:

private String timeLastChanged;

ou 

private Map<String, String> timeLastChanged;

Dans le premier exemple avec String, je rencontre le problème de la définition de timeLastChange = ServerValue.TIMESTAMP;, car ServerValue.TIMESTAMP est une carte.

Dans le deuxième exemple avec le Map<String, String>, le message d'erreur "échec de l'abattement" s'affiche car il ne parvient pas à désérialiser correctement les données stockées longtemps dans la base de données en un Map<String, String>. Y at-il un travail autour de cela?

23
Lyla

Mise à jour du 27/12/2016

Déconnecté @JsonIgnore pour @Exclude comme beaucoup l'ont mentionné.


J'ai finalement trouvé une solution flexible pour travailler avec Dates et ServerValue.TIMESTAMP. Ceci est basé sur des exemples de Ivan V , Ossama et puf

Je ne pouvais pas trouver un moyen de gérer la conversion entre long et HashMap<String, String>, mais si vous imbriquez la propriété dans un HashMap<String, Object> plus générique, elle peut être insérée dans la base de données sous la forme d'une seule valeur longue ("date", "1443765561874"). ou en tant que ServerValue.TIMESTAMP hash map ("date", {".sv", "servertime"}). Ensuite, lorsque vous le retirez, ce sera toujours un HashMap avec ("date", "un nombre long"). Vous pouvez ensuite créer une méthode d'assistance dans votre classe POJO à l'aide du @JsonIgnore Annotation @Exclude (ce qui signifie que Firebase l'ignorera et ne la traitera pas comme une méthode de sérialisation vers/depuis la base de données) pour obtenir facilement la valeur longue du HashMap renvoyé à utiliser dans votre application.

Exemple complet d'une classe POJO est ci-dessous:

import com.google.firebase.database.Exclude;
import com.firebase.client.ServerValue;

import Java.util.HashMap;
import Java.util.Map;

public class ExampleObject {
    private String name;
    private String owner;
    private HashMap<String, Object> dateCreated;
    private HashMap<String, Object> dateLastChanged;

    /**
     * Required public constructor
     */
    public ExampleObject() {
    }

    public ExampleObject(String name, String owner, HashMap<String,Object> dateCreated) {
        this.name = name;
        this.owner = owner;
        this.dateCreated = dateCreated;

        //Date last changed will always be set to ServerValue.TIMESTAMP
        HashMap<String, Object> dateLastChangedObj = new HashMap<String, Object>();
        dateLastChangedObj.put("date", ServerValue.TIMESTAMP);
        this.dateLastChanged = dateLastChangedObj;
    }

    public String getName() {
        return name;
    }

    public String getOwner() {
        return owner;
    }

    public HashMap<String, Object> getDateLastChanged() {
        return dateLastChanged;
    }

    public HashMap<String, Object> getDateCreated() {
      //If there is a dateCreated object already, then return that
        if (dateCreated != null) {
            return dateCreated;
        }
        //Otherwise make a new object set to ServerValue.TIMESTAMP
        HashMap<String, Object> dateCreatedObj = new HashMap<String, Object>();
        dateCreatedObj.put("date", ServerValue.TIMESTAMP);
        return dateCreatedObj;
    }

// Use the method described in https://stackoverflow.com/questions/25500138/Android-chat-crashes-on-datasnapshot-getvalue-for-timestamp/25512747#25512747
// to get the long values from the date object.
    @Exclude
    public long getDateLastChangedLong() {

        return (long)dateLastChanged.get("date");
    }

    @Exclude
    public long getDateCreatedLong() {
        return (long)dateCreated.get("date");
    }

}
28
Lyla

Je voulais améliorer la réponse de Lyla un peu. Premièrement, je voudrais me débarrasser des méthodes publiques public HashMap<String, Object> getDateLastChanged() public HashMap<String, Object> getDateCreated(). Pour ce faire, vous pouvez marquer la propriété dateCreated avec l'annotation @JsonProperty. Un autre moyen possible de le faire est de changer la détection de propriété comme suit: @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
Deuxièmement, je ne comprends pas pourquoi nous devons insérer ServerValue.TIMESTAMP dans HashMap alors que nous pouvons simplement les stocker en tant que propriété. Donc, mon code final est:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.firebase.client.ServerValue;

public class ShoppingList {
    private String listName;
    private String owner;
    @JsonProperty
    private Object created;

    public ShoppingList() {
    }

    public ShoppingList(String listName, String owner) {
        this.listName = listName;
        this.owner = owner;
        this.created = ServerValue.TIMESTAMP;
    }

    public String getListName() {
        return listName;
    }

    public String getOwner() {
        return owner;
    }

    @JsonIgnore
    public Long getCreatedTimestamp() {
        if (created instanceof Long) {
            return (Long) created;
        }
        else {
            return null;
        }
    }

    @Override
    public String toString() {
        return listName + " by " + owner;
    }

}
18
sergey.n

Cette solution me semble un peu difficile car je ne sais pas ce que fait @JsonIgnore. J'ai essayé de le faire facilement et semble travailler.

private Object dateLastChanged;

public Object getDateLastChanged() {
    return dateLastChanged;
}

Pour obtenir quelque chose de lisible par l'homme, je viens de dépasser la valeur de retour dateLastChanged Object dans la méthode suivante en le transformant en Long.

static String convertTime(Long unixtime) {
    Date dateObject = new Date(unixtime);
    SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MM-yy hh:mmaa");
    return dateFormatter.format(dateObject);
}

Bienvenue sur les avis sur ma solution ^^

7
Daniel Chan

Au lieu d'utiliser @JsonIgnore, vous pouvez utiliser le @Exclude..__ natif de Firebase. Par exemple, je travaille dans un projet similaire et mon modèle est comme cela.

package com.limte.app.borrador_1.mModel;

import com.google.firebase.database.Exclude;
import com.google.firebase.database.ServerValue;

/**
 * Created by Familia on 20/12/2016.
 */

public class ChatItem {
    String chatName;
    Long creationDate;


    public ChatItem() {
    }

    public String getChatName() {
        return chatName;
    }

    public void setChatName(String chatName) {
        this.chatName = chatName;
    }

    public Java.util.Map<String, String> getCreationDate() {
        return ServerValue.TIMESTAMP;
    }

    @Exclude
    public Long getCreationDateLong() {
        return creationDate;
    }
    public void setCreationDate(Long creationDate) {
        this.creationDate = creationDate;
    }

}

Et ce code fonctionne! Dans Firebase, les résultats sont les suivants: Résultats

5

Même solution, mais je l'utilise.

@IgnoreExtraProperties
public class FIRPost {
    Object timestamp;

    public FIRPost() {
        // Default constructor required for calls to DataSnapshot.getValue(FIRPost.class)
        this.timestamp = ServerValue.TIMESTAMP;
    }

    public Object getTimestamp() {
        return timestamp;
    }

    @Exclude
    public Long getTimestamp(boolean isLong) {
        if (timestamp instanceof Long) return (Long) timestamp;
        else return null;
    }
}
0
wonsuc

L'utilisation la plus courante de Server.TIMESTAMP est:

  1. définir la valeur du serveur lorsque les données sont envoyées sur le serveur
  2. récupérez ce modèle de firebase et lancez-le facilement en Long

Cette astuce m'a évité le dur labeur de gérer 2 champs différents pour seulement 1 valeur

    public class HandleTimestampFirebaseObject {

    Object timestamp;

    public HandleTimestampFirebaseObject() {

    }

    public Object getTimestamp(){
        if(timestamp instanceof Double){

      /*    this will handle the case of AFTER fetch from backend,and  
            serialize to object into SharedPreferences for example ,when the 
            Object casting automatically into Double.
            (Anyway,call (long)getTimestamp from your code who use this model*/
            return ((Double) timestamp).longValue();
        }
        else{
            return timestamp;  //this handle to firebase requirement in the server side(Object needed)
        }
    }
0
yarin