Apper med Firebase Auth og Realtime Database · leksjon

Transaksjonelle dataoperasjoner

Lær å bruke transaksjoner for å forhindre race conditions og sikre atomiske oppdateringer av kritiske data

Leksjon 2 av 411 trinn

Transaksjonelle dataoperasjoner er en gratis leksjon i Apper med Firebase Auth og Realtime Database på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Apper med Firebase Auth og Realtime Database, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Apper med Firebase Auth og Realtime Database inneholder totalt 4 leksjoner.

Hvorfor dataintegritet er viktig

I sanntidsapplikasjoner kan flere brukere forsøke å oppdatere de samme dataene samtidig. Hvis dette ikke håndteres riktig, kan det føre til alvorlige problemer som ødelagte eller inkonsistente data.

Se for Dem en enkel teller på et nettsted. Hvis to brukere klikker på «Liker» akkurat samtidig, skal telleren økes med to, ikke bare én.

Problemet med kappløpstilstander

Uten riktig synkronisering kan det oppstå en vanlig situasjon som kalles en kappløpstilstand. Dette skjer når resultatet av en operasjon avhenger av den uforutsigbare rekkefølgen eller timingen til andre operasjoner.

Hvis De for eksempel leser en verdi, øker den og deretter skriver den tilbake, kan en annen bruker lese den opprinnelige verdien før De skriver den økte verdien. Da kan en oppdatering gå tapt.

Introduksjon til Firebase Transactions

Firebase Realtime Database tilbyr en kraftig funksjon kalt transactions for å løse kappløpstilstander og sikre dataintegriteten. En transaksjon garanterer en atomisk oppdatering.

Atomisk betyr at operasjonen enten fullføres i sin helhet, eller ikke skjer i det hele tatt. Det er som ett enkelt, udelelig trinn.

Slik fungerer `runTransaction`

De starter en transaksjon ved å bruke metoden runTransaction() på en DatabaseReference. Denne metoden tar imot en tilbakeringing av typen Transaction.Handler.

  • Firebase sender den gjeldende tilstanden til behandleren.
  • De endrer disse dataene i behandleren.
  • Hvis en annen klient skriver til samme sted mens transaksjonen kjører, prøver Firebase automatisk transaksjonen på nytt med de nye gjeldende dataene.

Implementere en trygg teller

La oss se hvordan De trygt kan øke en teller ved hjelp av en transaksjon. Dette sikrer at telleren alltid blir riktig, selv om flere brukere prøver å øke den samtidig.

Prøv å kjøre dette eksempelet:

public class Main {

  // Mock Firebase classes for demonstration
  static class MockFirebaseDatabase {
    private Integer value = 0; // Simulate data at a path
    public Integer get() { return value; }
    public void set(Integer val) { value = val; }

    public interface TransactionHandler {
      TransactionResult doTransaction(MutableData currentData);
    }

    public static class MutableData {
      private Integer data;
      public MutableData(Integer data) { this.data = data; }
      public Integer getValue() { return data; }
      public void setValue(Integer data) { this.data = data; }
    }

    public static class TransactionResult {
      private boolean success;
      private MutableData newData;
      private TransactionResult(boolean success, MutableData newData) {
        this.success = success;
        this.newData = newData;
      }
      public static TransactionResult success(MutableData newData) {
        return new TransactionResult(true, newData);
      }
      public static TransactionResult abort() {
        return new TransactionResult(false, null);
      }
      public boolean isSuccess() { return success; }
      public MutableData getNewData() { return newData; }
    }

    public void runTransaction(TransactionHandler handler) {
      // Simulate read, modify, and retry logic
      MutableData currentData = new MutableData(this.get());
      TransactionResult result = handler.doTransaction(currentData);

      if (result.isSuccess()) {
        this.set(result.getNewData().getValue());
        System.out.println("Transaction committed. New value: " + this.get());
      } else {
        System.out.println("Transaction aborted.");
      }
    }
  }

  public static void main(String[] args) {
    MockFirebaseDatabase counterRef = new MockFirebaseDatabase();
    counterRef.set(5); // Initial value

    counterRef.runTransaction(new MockFirebaseDatabase.TransactionHandler() {
      @Override
      public MockFirebaseDatabase.TransactionResult doTransaction(MockFirebaseDatabase.MutableData currentData) {
        Integer currentValue = currentData.getValue();
        if (currentValue == null) {
          currentValue = 0;
        }
        currentData.setValue(currentValue + 1);
        return MockFirebaseDatabase.TransactionResult.success(currentData);
      }
    });
  }
}

Forstå `MutableData`

Inne i Transaction.Handler representerer objektet MutableData dataene på databaseplasseringen De prøver å endre.

  • Bruk currentData.getValue() for å lese den eksisterende verdien.
  • Bruk currentData.setValue(newValue) for å angi den nye verdien De vil skrive.

Husk at dette er dataene Firebase vil forsøke å lagre. Hvis det oppstår en konflikt, kalles behandleren på nytt med oppdaterte MutableData-data.

`TransactionResult` og avbryting

Etter at MutableData er behandlet, må behandleren returnere en Transaction.Result:

  • Transaction.Result.success(mutableData): Ber Firebase forsøke å lagre den nye verdien i mutableData.
  • Transaction.Result.abort(): Ber Firebase avbryte transaksjonen. Dette er nyttig hvis dataene har en uventet tilstand, eller hvis logikken avgjør at transaksjonen ikke skal fortsette.

Her er et eksempel på hvordan en transaksjon avbrytes:

public class Main {

  // Mock Firebase classes (repeated for full program requirement)
  static class MockFirebaseDatabase {
    private Integer value = 0;
    public Integer get() { return value; }
    public void set(Integer val) { value = val; }

    public interface TransactionHandler {
      TransactionResult doTransaction(MutableData currentData);
    }

    public static class MutableData {
      private Integer data;
      public MutableData(Integer data) { this.data = data; }
      public Integer getValue() { return data; }
      public void setValue(Integer data) { this.data = data; }
    }

    public static class TransactionResult {
      private boolean success;
      private MutableData newData;
      private TransactionResult(boolean success, MutableData newData) {
        this.success = success;
        this.newData = newData;
      }
      public static TransactionResult success(MutableData newData) {
        return new TransactionResult(true, newData);
      }
      public static TransactionResult abort() {
        return new TransactionResult(false, null);
      }
      public boolean isSuccess() { return success; }
      public MutableData getNewData() { return newData; }
    }

    public void runTransaction(TransactionHandler handler) {
      MutableData currentData = new MutableData(this.get());
      TransactionResult result = handler.doTransaction(currentData);

      if (result.isSuccess()) {
        this.set(result.getNewData().getValue());
        System.out.println("Transaction committed. New value: " + this.get());
      } else {
        System.out.println("Transaction aborted.");
      }
    }
  }

  public static void main(String[] args) {
    MockFirebaseDatabase statusRef = new MockFirebaseDatabase();
    statusRef.set(1); // 1 = Active, 0 = Inactive

    // Try to change status, but abort if it's already Inactive (0)
    statusRef.runTransaction(new MockFirebaseDatabase.TransactionHandler() {
      @Override
      public MockFirebaseDatabase.TransactionResult doTransaction(MockFirebaseDatabase.MutableData currentData) {
        Integer status = currentData.getValue();
        if (status != null && status == 0) {
          System.out.println("Status is already Inactive. Aborting transaction.");
          return MockFirebaseDatabase.TransactionResult.abort();
        }
        // Change status to 0 (Inactive)
        currentData.setValue(0);
        return MockFirebaseDatabase.TransactionResult.success(currentData);
      }
    });
  }
}

Håndtere fullføring av transaksjonen

Etter at De har kalt runTransaction(), vil De vanligvis vite om den lyktes eller mislyktes. Firebase tilbyr en onComplete-tilbakeringing for dette.

Denne tilbakeringingen gir Dem:

  • error: Hvis transaksjonen mislyktes.
  • committed: En boolsk verdi som angir om transaksjonen ble lagret.
  • currentData: Den endelige tilstanden til dataene.

Bruk denne tilbakeringingen til å oppdatere brukergrensesnittet eller håndtere logikk som skal utføres etter transaksjonen.

Utover enkle tellere

Transaksjoner er uvurderlige i alle situasjoner som krever sterk datakonsistens:

  • Unike brukernavn: Sørg for at et brukernavn faktisk er unikt før det tildeles.
  • Stemmesystemer: Forhindre dobbeltstemming eller sørg for at stemmetallene er riktige.
  • Lagerstyring: Reduser lagernivåer på en trygg måte uten å selge mer enn det som finnes på lager.
  • Spillpoeng: Oppdater toppresultater pålitelig i flerspillerspill.

Kort kontroll

Transaksjoner er avgjørende for å opprettholde dataintegritet i miljøer med samtidige operasjoner. Hvilket av de følgende beskriver best den viktigste fordelen ved å bruke transaksjoner i Firebase Realtime Database?

Oppsummering og neste steg

De har lært om den viktige rollen transaksjonsbaserte dataoperasjoner spiller for å opprettholde dataintegritet i sanntidsapplikasjoner.

  • Vi utforsket kappløpstilstander og hvorfor de er problematiske.
  • De forstår nå hvordan Firebases runTransaction()-metode sikrer atomiske oppdateringer.
  • Vi så eksempler på trygg økning av tellere og bruk av Transaction.Result.abort().

Transaksjoner er et kraftig verktøy, men bruk dem med omtanke, siden de kan være tregere enn direkte skriveoperasjoner. I neste leksjon skal vi se nærmere på atomiske tellere og køer!

Gratis å komme i gang

Lær deg Apper med Firebase Auth og Realtime Database med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
11
Leksjoner
44

Ofte stilte spørsmål

Er leksjonen «Transaksjonelle dataoperasjoner» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Apper med Firebase Auth og Realtime Database, inkludert «Transaksjonelle dataoperasjoner», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Apper med Firebase Auth og Realtime Database inneholder totalt 4 leksjoner.

Hva lærer jeg i «Transaksjonelle dataoperasjoner»?

Lær å bruke transaksjoner for å forhindre race conditions og sikre atomiske oppdateringer av kritiske data Du øver på Apper med Firebase Auth og Realtime Database med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Apper med Firebase Auth og Realtime Database?

Ingen tidligere erfaring er nødvendig. Apper med Firebase Auth og Realtime Database på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Transaksjonelle dataoperasjoner»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Apper med Firebase Auth og Realtime Database-leksjonen?

Ja. Alle Apper med Firebase Auth og Realtime Database-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Fan-out-oppdateringer av data
  2. Transaksjonelle dataoperasjoner
  3. Atomiske tellere og køer
  4. Strategier for denormalisering og dataduplisering
← Tilbake til Apper med Firebase Auth og Realtime Database