Как проверить, что определенные данные уже существуют в пожарном депо или нет - PullRequest
0 голосов
/ 23 июня 2018

Перед добавлением новых данных в пожарный магазин я хочу проверить, что в базе данных уже есть данные того же типа или нет. Если данные уже присутствуют, значит, я хочу запретить пользователю вводить дубликаты данных в базу данных.,В моем случае это похоже на бронирование по предварительной записи, если уже существует бронирование на то же время, я хочу запретить пользователям бронировать в одно и то же время. Я пытался использовать функцию запроса, но это не мешает вводу дубликатов данных.

private boolean alreadyBooked(final String boname, final String bodept, final String botime) {
        final int[] flag = {0};
        CollectionReference cref=db.collection("bookingdetails");
        Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
        q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                for (DocumentSnapshot ds : queryDocumentSnapshots) {
                    String rname, rdept, rtime;
                    rname = ds.getString("name");
                    rdept = ds.getString("dept");
                    rtime = ds.getString("time");
                    if (rdept.equals(botime)) {
                        if (rtime.equals(botime)) {
                            flag[0] = 1;
                            return;
                        }
                    }
                }
            }
        });
        if(flag[0]==1){
            return true;
        }
        else {
            return false;
        }
    }

1 Ответ

0 голосов
/ 23 июня 2018

Загрузка данных из Cloud Firestore происходит асинхронно.К тому времени, как вы вернетесь из alreadyBooked, данные еще не загружены, onSuccess еще не запущен, а flag все еще имеет значение по умолчанию.

Самый простой способ убедиться в этомс несколькими инструкциями журнала:

private boolean alreadyBooked(final String boname, final String bodept, final String botime) {
    CollectionReference cref=db.collection("bookingdetails");
    Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
    System.out.println("Starting listener");
    q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
            System.out.println("Got data from Firestore");
        }
    });
    System.out.println("Returning");
}

Если вы запустите этот код, он напечатает:

Запуск слушателя

Возвращение

Получил данныеиз Firestore

Вероятно, это не тот порядок, который вы ожидали.Но это прекрасно объясняет, почему вы всегда получаете false при вызове alreadyBooked: данные просто не возвращаются из Firestore вовремя.

Решение для этого состоит в том, чтобы изменить ваш взгляд на проблему,В вашем текущем коде есть логика: «Сначала проверьте, забронирован ли он, а затем добавьте новый элемент».Нам нужно перефразировать это следующим образом: «Начните проверять, забронировано ли оно. Как только мы узнаем, что это не так, добавьте новый элемент».В коде это означает, что весь код, которому нужны данные из Firestore, должен находиться внутри onSuccess или должен вызываться оттуда.

Самая простая версия - переместить код в onSuccess:

private void alreadyBooked(final String boname, final String bodept, final String botime) {
    CollectionReference cref=db.collection("bookingdetails");
    Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
    q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
            boolean isExisting = false
            for (DocumentSnapshot ds : queryDocumentSnapshots) {
                String rname, rdept, rtime;
                rname = ds.getString("name");
                rdept = ds.getString("dept");
                rtime = ds.getString("time");
                if (rdept.equals(botime)) {
                    if (rtime.equals(botime)) {
                        isExisting = true;
                    }
                }
            }
            if (!isExisting) {
                // TODO: add item to Firestore
            }
        }
    });
}

Хотя это очень просто, он делает alreadyBooked менее пригодным для повторного использования, поскольку теперь он содержит код для вставки нового элемента.Вы можете решить эту проблему, определив свой собственный интерфейс обратного вызова:

public interface AlreadyBookedCallback {
  void onCallback(boolean isAlreadyBooked);
}

private void alreadyBooked(final String boname, final String bodept, final String botime, AlreadyBookedCallback callback) {
    CollectionReference cref=db.collection("bookingdetails");
    Query q1=cref.whereEqualTo("time",botime).whereEqualTo("dept",bodept);
    q1.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
        @Override
        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
            for (DocumentSnapshot ds : queryDocumentSnapshots) {
                String rname, rdept, rtime;
                rname = ds.getString("name");
                rdept = ds.getString("dept");
                rtime = ds.getString("time");
                if (rdept.equals(botime)) {
                    if (rtime.equals(botime)) {
                        isExisting = true;
                    }
                }
            }
            callback.onCallback(isExisting)
        }
    });
}

И затем вы называете это как:

alreadyBooked(boname, bodept, botime, new AlreadyBookedCallback() {
  @Override
  public void onCallback(boolean isAlreadyBooked) {
    // TODO: insert item
  }
});

Также смотрите (многие из них для базы данных реального времени Firebase, гдеприменяется та же логика):

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...