2017-02-04 8 views
0

Скажем, у меня есть проект с узлом «пользователи» и «домашним» узлом. Когда пользователь получает домашнее животное, я хочу, чтобы оба добавляли ключ домашнего животного на узел «домашних животных» пользователя и идентификатор пользователя на узел владельца «домашних животных».Создание транзакции Android Firebase, которая модифицирует несколько узлов

Пример:

{ 
    "users":{ 
     "user1":{ 
      "pets":{ 
       "pet1":true, 
       "pet3":true 
      } 
      ... 
     } 
    }, 
    "pets":{ 
     "pet1":{ 
      "owner":"user1", 
      ... 
     }, 
     ... 
    } 
} 

Я хочу, чтобы убедиться, что оба обновления удастся предотвратить несогласованное состояние.

Я читал о том, как работать с Firebase сделок here, однако, когда я пытаюсь создать транзакцию, которая изменяет соответствующие значения (с помощью dbRef.runTransaction (...)), я получаю эту ошибку DatabaseError:

The transaction had too many retries

Только транзакция работает, когда я вызываю runTransaction() на конкретном узле, который я модифицирую (например, вызывая dbRef.child («users»). Child («user1»). RunTransaction (...)), однако это не помогает мне, потому что мне нужно связаться как с соответствующим пользователем, так и с домашним животным.

Как я могу совершить эту транзакцию?

+0

Сообщение об ошибке означает, что у вас слишком много споров относительно обновлений. Решение, как правило, заключается в том, чтобы снизить транзакцию в дерево, чтобы уменьшить конкуренцию. Но, не видя проблемного кода, трудно быть конкретным. –

ответ

5

Согласно Firebase Docs, вам не нужно использовать операцию транзакции (я объясню это позже).

Для того, чтобы сохранить данные в нескольких узлах в ONE ПАКЕТА, я советую вам построить карту <> массив, в котором Key представляет собой путь, и Value представляет, хорошо, независимо от вы хотите сохранить внутри.

Позволяет сказать "user1" просто стал обладателем "pet4", и ваш dbRereference указывает на корневой каталог:

FirebaseDatabase dbRef = FirebaseDatabase.getInstance().getReference(); 

Map<String, Object> update = new HashMap<>(); 
update.put("users/user1/pets/pet4", true); 
update.put("pets/pet4/owner", "user4"); 

Позже вы можете запустить .updateChildren (Карта <,>) и присоедините слушателя.

dbRef.updateChildren(update).addOnCompleteListener(new OnCompleteListener<Void>() { 
    @Override 
    public void onComplete(@NonNull Task<Void> task) { 
     if (task.isSuccessful()) 
      Log.d("Success!"); 
     else 
      Log.d("Failure"); 
    } 
}); 

Таким образом, если произошел сбой, ваша база данных не будет изменена вообще.

«Транзакция» - это термин, который Firebase дал для другой операции, которая, по моему мнению, послужила причиной вашей путаницы: она используется при работе с данными, которые могут быть повреждены с помощью одновременных модификаций, таких как инкрементные счетчики. Для дальнейшего чтения откройте ссылку, прикрепленную в начале.

+0

Я также пробовал использовать updateChildren, но это вызвало еще одну проблему. Скажем, что «user1» уже имеет домашнее животное в своем «домашнем» узле, используя updateChildren(), похоже, переопределяет это домашнее животное и размещает там только новое домашнее животное. Так что, если, например, «user1» имел «pet1» в узле «домашние животные», и я использовал update.put («users/user1/pets/pet4», true), теперь у него будет только «pet4» под «pets», , – dors

+1

Вы уверены, что указываете свой ключ на LAST-узел под названием «pet4»? updateChildren переопределяет только то значение, которое вы предоставляете, и только внутри «самого глубокого» узла, который вы предоставляете.Если вы говорите, что весь узел «домашних животных» изменен, я могу только предположить, что вы ошибочно редактируете узел над ним, что является «домашним животным». Попробуйте убедиться, что вы указываете точное местоположение в обновлении, которое является «pet4». Я использую эту функцию много, и она работает как шарм :) – Barackos

 Смежные вопросы

  • Нет связанных вопросов^_^