Vanlige dvaleundtak

1. Introduksjon

I denne opplæringen vil vi diskutere noen vanlige unntak vi kan støte på mens vi jobber med dvalemodus.

Vi vil gjennomgå formålet og noen vanlige årsaker. I tillegg vil vi se på løsningene deres.

2. Oversikt over dvaleundtak

Mange forhold kan føre til at unntak kastes mens du bruker dvalemodus. Dette kan være kartleggingsfeil, infrastrukturproblemer, SQL-feil, brudd på dataintegritet, øktproblemer og transaksjonsfeil.

Disse unntakene strekker seg stort sett fra HibernateException. Imidlertid, hvis vi bruker Hibernate som en JPA-utholdenhetsleverandør, kan disse unntakene bli pakket inn i PersistenceException.

Begge disse basisklassene strekker seg fra RuntimeException. Derfor er de alle ukontrollerte. Derfor trenger vi ikke å fange eller erklære dem på hvert sted de brukes.

Dessuten, de fleste av disse er uopprettelige. Som et resultat, ville det ikke hjelpe å prøve å operere på nytt. Dette betyr at vi må forlate den gjeldende økten når vi møter dem.

La oss nå se på hver av disse, en om gangen.

3. Kartleggingsfeil

Objektrelasjonell kartlegging er en stor fordel med dvalemodus. Spesielt frigjør det oss fra å skrive SQL-setninger manuelt.

Samtidig krever det at vi spesifiserer kartleggingen mellom Java-objekter og databasetabeller. Følgelig spesifiserer vi dem ved hjelp av merknader eller gjennom kartleggingsdokumenter. Disse tilordningene kan kodes manuelt. Alternativt kan vi bruke verktøy for å generere dem.

Mens vi spesifiserer disse tilordningene, kan vi gjøre feil. Disse kan være i kartleggingsspesifikasjonen. Eller det kan være et misforhold mellom et Java-objekt og den tilsvarende databasetabellen.

Slike kartfeil genererer unntak. Vi kommer ofte over dem under den første utviklingen. I tillegg kan vi støte på dem mens vi migrerer endringer over miljøer.

La oss se på disse feilene med noen eksempler.

3.1. MappingException

Et problem med objekt-relasjonell kartlegging forårsaker a MappingException å bli kastet:

offentlig ugyldig nårQueryExecutedWithUnmappedEntity_thenMappingException () {throw.expectCause (isA (MappingException.class)); throw.expectMessage ("Ukjent enhet: java.lang.String"); Sessionsøkt = sessionFactory.getCurrentSession (); NativeQuery-spørring = økt .createNativeQuery ("velg navn fra PRODUKT", String.class); query.getResultList (); }

I koden ovenfor er createNativeQuery metoden prøver å tilordne søkeresultatet til den angitte Java-typen String. Den bruker den implisitte kartleggingen av String klasse fra Metamodell å gjøre kartleggingen.

Imidlertid, den String klasse har ikke noen kartlegging spesifisert. Derfor vet ikke dvalemodus hvordan man skal kartlegge Navn kolonne til String og kaster unntaket.

For en detaljert analyse av mulige årsaker og løsninger, sjekk ut unntak for dvalemodus - ukjent enhet.

Tilsvarende kan andre feil også forårsake dette unntaket:

  • Blanding av merknader om felt og metoder
  • Kunne ikke spesifisere @JoinTable for en @ManyToMany assosiasjon
  • Standardkonstruktøren for den tilordnede klassen gir et unntak under kartleggingsbehandling

Dessuten, MappingException har noen underklasser som kan indikere spesifikke kartleggingsproblemer:

  • Kommentar unntak - et problem med en kommentar
  • DuplicateMappingException - duplikatkartlegging for et klasse-, tabell- eller eiendomsnavn
  • InvalidMappingException - kartleggingen er ugyldig
  • MappingNotFoundException - kartleggingsressursen ble ikke funnet
  • PropertyNotFoundException - en forventet getter- eller settermetode ble ikke funnet på en klasse

Derfor, hvis vi kommer over dette unntaket, bør vi først bekrefte kartleggingen.

3.2. Kommentar unntak

For å forstå Kommentar unntak, la oss opprette en enhet uten en identifikatorkommentar på noe felt eller eiendom:

@Entity offentlig klasse EntityWithNoId {privat int id; public int getId () {return id; } // standard setter}

Siden Dvalemodus forventer at alle enheter har en identifikator, vi får en Kommentar unntak når vi bruker enheten:

offentlig tomrom givenEntityWithoutId_whenSessionFactoryCreated_thenAnnotationException () {throw.expect (AnnotationException.class); throw.expectMessage ("Ingen identifikator spesifisert for enheten"); Konfigurasjon cfg = getConfiguration (); cfg.addAnnotatedClass (EntityWithNoId.class); cfg.buildSessionFactory (); }

Videre er noen andre sannsynlige årsaker:

  • Ukjent sekvensgenerator brukt i @GeneratedValue kommentar
  • @Temporal kommentar brukt med en Java 8 Dato/Tid klasse
  • Målenhet mangler eller ikke eksisterer for @ManyToOne eller @OneToMany
  • Rå samlingsklasser brukt med forholdsmerknader @OneToMany eller @ManyToMany
  • Betongklasser brukt med samlingens merknader @OneToMany, @ManyToMany eller @ElementCollection som dvalemodus forventer samlingsgrensesnittene

For å løse dette unntaket, bør vi først sjekke den spesifikke merknaden som er nevnt i feilmeldingen.

4. Feil i skjemastyring

Automatisk databaseskjemahåndtering er en annen fordel med dvalemodus. For eksempel kan den generere DDL-setninger for å opprette eller validere databaseobjekter.

For å bruke denne funksjonen, må vi stille inn dvale.hbm2ddl.auto eiendom riktig.

Hvis det er problemer mens du utfører skjemahåndtering, får vi et unntak. La oss undersøke disse feilene.

4.1. SchemaManagementException

Ethvert infrastrukturrelatert problem ved utføring av skjemadministrasjon forårsaker a SchemaManagementException.

For å demonstrere, la oss instruere dvalemodus om å validere databaseskjemaet:

offentlig tomrom givenMissingTable_whenSchemaValidated_thenSchemaManagementException () {throw.expect (SchemaManagementException.class); throw.expectMessage ("Skjemavalidering: manglende tabell"); Konfigurasjon cfg = getConfiguration (); cfg.setProperty (AvailableSettings.HBM2DDL_AUTO, "validere"); cfg.addAnnotatedClass (Product.class); cfg.buildSessionFactory (); }

Siden tabellen tilsvarer Produkt ikke er til stede i databasen, får vi unntaket for skjemavalidering mens vi bygger SessionFactory.

I tillegg er det andre mulige scenarier for dette unntaket:

  • kan ikke koble til databasen for å utføre skjemaadministrasjonsoppgaver
  • skjemaet er ikke til stede i databasen

4.2. CommandAcceptanceException

Ethvert problem med å utføre en DDL som tilsvarer en spesifikk skjemaadministrasjonskommando, kan forårsake a CommandAcceptanceException.

La oss som et eksempel spesifisere feil dialekt mens du setter opp SessionFactory:

offentlig ugyldig når WrongDialectSpecified_thenCommandAcceptanceException () {throw.expect (SchemaManagementException.class); kastet.expectCause (isA (CommandAcceptanceException.class)); throw.expectMessage ("Stopp ved feil: Feil ved kjøring av DDL"); Konfigurasjon cfg = getConfiguration (); cfg.setProperty (AvailableSettings.DIALECT, "org.hibernate.dialect.MySQLDialect"); cfg.setProperty (AvailableSettings.HBM2DDL_AUTO, "oppdatering"); cfg.setProperty (AvailableSettings.HBM2DDL_HALT_ON_ERROR, "true"); cfg.getProperties () .put (AvailableSettings.HBM2DDL_HALT_ON_ERROR, sant); cfg.addAnnotatedClass (Product.class); cfg.buildSessionFactory (); }

Her har vi spesifisert feil dialekt: MySQLDialect. Vi instruerer også dvalemodus om å oppdatere skjemaobjektene. Derfor mislykkes DDL-setningene som er utført av Hibernate for å oppdatere H2-databasen, og vi får et unntak.

Som standard logger dvalemodus dette unntaket stille og går videre. Når vi senere bruker Sesjonsfabrikk, vi får unntaket.

For å sikre at det oppstår et unntak for denne feilen, har vi angitt eiendommen HBM2DDL_HALT_ON_ERROR til ekte.

På samme måte er dette noen andre vanlige årsaker til denne feilen:

  • Det er et misforhold i kolonnenavn mellom kartlegging og databasen
  • To klasser er kartlagt til samme bord
  • Navnet som brukes for en klasse eller tabell er et reservert ord i databasen, som BRUKER, for eksempel
  • Brukeren som ble brukt til å koble til databasen, har ikke det nødvendige privilegiet

5. SQL-kjøringsfeil

Når vi setter inn, oppdaterer, sletter eller spørrer om data ved hjelp av dvalemodus, utfører den DML-setninger mot databasen ved hjelp av JDBC. Denne API-en reiser en SQLException hvis operasjonen resulterer i feil eller advarsler.

Dvalemodus konverterer dette unntaket til JDBCEeksepsjon eller en av dens egnede underklasser:

  • ConstraintViolationException
  • DataException
  • JDBCConnectionException
  • LockAcquisitionException
  • PessimisticLockException
  • QueryTimeoutException
  • SQLGrammarException
  • GeneriskJDBCEeksepsjon

La oss diskutere vanlige feil.

5.1. JDBCEeksepsjon

JDBCEeksepsjon er alltid forårsaket av en bestemt SQL-setning. Vi kan ringe getSQL metode for å få den fornærmende SQL-setningen.

Videre kan vi hente det underliggende SQLException med getSQLException metode.

5.2. SQLGrammarException

SQLGrammarException indikerer at SQL sendt til databasen var ugyldig. Det kan skyldes en syntaksfeil eller en ugyldig objektreferanse.

For eksempel, en manglende tabell kan resultere i denne feilen mens du spør etter data:

offentlig tomrom givenMissingTable_whenQueryExecuted_thenSQLGrammarException () {throw.expect (isA (PersistenceException.class)); kastet.expectCause (isA (SQLGrammarException.class)); throw.expectMessage ("SQLGrammarException: kunne ikke forberede uttalelse"); Sessionsøkt = sessionFactory.getCurrentSession (); NativeQuery spørring = session.createNativeQuery ("velg * fra NON_EXISTING_TABLE", Product.class); query.getResultList (); }

Vi kan også få denne feilen mens vi lagrer data hvis tabellen mangler:

offentlig ugyldighet givenMissingTable_whenEntitySaved_thenSQLGrammarException () {throw.expect (isA (PersistenceException.class)); kastet.expectCause (isA (SQLGrammarException.class)); kastet .expectMessage ("SQLGrammarException: kunne ikke forberede uttalelse"); Konfigurasjon cfg = getConfiguration (); cfg.addAnnotatedClass (Product.class); SessionFactory sessionFactory = cfg.buildSessionFactory (); Øktøkt = null; Transaksjonstransaksjon = null; prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (1); product.setName ("Produkt 1"); session.save (produkt); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); closeSessionFactoryQuietly (sessionFactory); }}

Noen andre mulige årsaker er:

  • Navnestrategien som brukes, tilordner ikke klassene til de riktige tabellene
  • Kolonnen spesifisert i @JoinColumn eksisterer ikke

5.3. ConstraintViolationException

EN ConstraintViolationException indikerer at den forespurte DML-operasjonen førte til at en integritetsbegrensning ble brutt. Vi kan få navnet på denne begrensningen ved å ringe getConstraintName metode.

En vanlig årsak til dette unntaket er å prøve å lagre duplikatposter:

offentlig ugyldig nårDuplicateIdSaved_thenConstraintViolationException () {throw.expect (isA (PersistenceException.class)); throw.expectCause (isA (ConstraintViolationException.class)); throw.expectMessage ("ConstraintViolationException: kunne ikke utføre uttalelse"); Øktøkt = null; Transaksjonstransaksjon = null; for (int i = 1; i <= 2; i ++) {prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (1); product.setName ("Produkt" + i); session.save (produkt); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); }}}

Sparer også en null verdi til en IKKE NULL kolonnen i databasen kan øke denne feilen.

For å løse denne feilen, vi bør utføre alle valideringer i forretningslaget. Videre bør databasebegrensninger ikke brukes til å validere applikasjoner.

5.4. DataException

DataException indikerer at evalueringen av en SQL-setning resulterte i ulovlig drift, typefeil eller feil kardinalitet.

For eksempel kan bruk av tegndata mot en numerisk kolonne forårsake denne feilen:

offentlig ugyldig gittQueryWithDataTypeMismatch_WhenQueryExecuted_thenDataException () {throw.expectCause (isA (DataException.class)); throw.expectMessage ("org.hibernate.exception.DataException: kunne ikke utarbeide uttalelse"); Sessionsøkt = sessionFactory.getCurrentSession (); NativeQuery spørring = session.createNativeQuery ("velg * fra PRODUKT der", Product.class); query.getResultList (); }

For å fikse denne feilen, vi bør sørge for at datatypene og lengden samsvarer mellom applikasjonskoden og databasen.

5.5. JDBCConnectionException

EN JDBCConectionException indikerer problemer med å kommunisere med databasen.

For eksempel kan en database eller et nettverk som går ned, føre til at dette unntaket blir kastet.

I tillegg kan feil databaseoppsett forårsake dette unntaket. Et slikt tilfelle er at databaseforbindelsen ble stengt av serveren fordi den var inaktiv i lang tid. Dette kan skje hvis vi bruker tilkoblingssamling og tomgangsinnstillingen for inaktivitet i bassenget er mer enn verdien for tilkoblingstidsavbrudd i databasen.

For å løse dette problemet, bør vi først sørge for at databaseverten er til stede og at den er oppe. Deretter bør vi verifisere at riktig autentisering brukes til databasetilkoblingen. Til slutt bør vi sjekke at tidsavbruddsverdien er riktig satt i tilkoblingsbassenget.

5.6. QueryTimeoutException

Når en databasespørsmål går ut, får vi dette unntaket. Vi kan også se det på grunn av andre feil, for eksempel at tabellområdet blir fullt.

Dette er en av få feil som kan gjenopprettes, noe som betyr at vi kan prøve uttalelsen på nytt i samme transaksjon.

For å løse dette problemet, vi kan øke spørretidsavbruddet for langvarige spørsmål på flere måter:

  • Sett pause element i en @NamedQuery eller @NamedNativeQuery kommentar
  • Påkalle setHint Metode av spørringen grensesnitt
  • Ring setTimeout metoden for Transaksjon grensesnitt
  • Påkalle setTimeout metoden for Spørsmål grensesnitt

6. Sesjonsstatusrelaterte feil

La oss nå se på feil på grunn av feil i dvalemodus.

6.1. NonUniqueObjectException

Dvalemodus tillater ikke to objekter med samme identifikator i en enkelt økt.

Hvis vi prøver å knytte to forekomster av samme Java-klasse til samme identifikator i en enkelt økt, får vi en NonUniqueObjectException. Vi kan få navnet og identifikatoren til enheten ved å ringe getEntityName () og getIdentifier () metoder.

For å gjengi denne feilen, la oss prøve å lagre to forekomster av Produkt med samme ID med en økt:

offentlig tomrom givenSessionContainingAnId_whenIdAssociatedAgain_thenNonUniqueObjectException () {throw.expect (isA (NonUniqueObjectException.class)); throw.expectMessage ("Et annet objekt med samme identifikasjonsverdi var allerede knyttet til økten"); Øktøkt = null; Transaksjonstransaksjon = null; prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (1); product.setName ("Produkt 1"); session.save (produkt); produkt = nytt produkt (); product.setId (1); product.setName ("Produkt 2"); session.save (produkt); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); }}

Vi får en NonUniqueObjectException, som forventet.

Dette unntaket forekommer ofte når du kobler et løsrevet objekt til en økt på nytt ved å ringe til Oppdater metode. Hvis økten har en annen forekomst med samme identifikator lastet, får vi denne feilen. For å fikse dette, vi kan bruke slå sammen metode for å feste det løsrevne objektet på nytt.

6.2. StaleStateException

Dvalemoduskast StaleStateExceptions når versjonsnummeret eller tidsstempelkontrollen mislykkes. Det indikerer at økten inneholdt foreldede data.

Noen ganger blir dette pakket inn i en OptimisticLockException.

Denne feilen oppstår vanligvis når du bruker langvarige transaksjoner med versjonering.

I tillegg kan det også skje mens du prøver å oppdatere eller slette en enhet hvis den tilsvarende databaseraden ikke eksisterer:

offentlig ugyldig nårUpdatingNonExistingObject_thenStaleStateException () {throw.expect (isA (OptimisticLockException.class)); throw.expectMessage ("Batchoppdatering returnerte uventet radtall fra oppdatering"); kastet.expectCause (isA (StaleStateException.class)); Øktøkt = null; Transaksjonstransaksjon = null; prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (15); product.setName ("Product1"); session.update (produkt); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); }}

Noen andre mulige scenarier er:

  • vi spesifiserte ikke en riktig strategi for ikke-lagret verdi for enheten
  • to brukere prøvde å slette den samme raden nesten samtidig
  • vi angir en verdi manuelt i det autogenererte ID- eller versjonsfeltet

7. Lat initialiseringsfeil

Vi konfigurerer vanligvis assosiasjoner som skal lastes lat for å forbedre applikasjonsytelsen. Foreningene hentes bare når de først brukes.

Dvalemodus krever imidlertid en aktiv økt for å hente data. Hvis økten allerede er stengt når vi prøver å få tilgang til en ikke-initialisert tilknytning, får vi et unntak.

La oss se på dette unntaket og de forskjellige måtene å fikse det på.

7.1. LazyInitializationException

LazyInitializationException indikerer et forsøk på å laste inn ikke-initialiserte data utenfor en aktiv økt. Vi kan få denne feilen i mange scenarier.

Først kan vi få dette unntaket mens vi får tilgang til et lat forhold i presentasjonslaget. Årsaken er at enheten ble delvis lastet inn i virksomhetslaget og økten ble avsluttet.

For det andre kan vi få denne feilen med Spring Data hvis vi bruker få en metode. Denne metoden henter forekomsten lat.

Det er mange måter å løse dette unntaket på.

Først og fremst kan vi gjøre alle forhold ivrig lastet.Men dette vil påvirke programytelsen fordi vi laster inn data som ikke blir brukt.

For det andre kan vi holde økten åpen til visningen er gjengitt. Dette er kjent som “Åpne økt i visning”Og det er et antimønster. Vi bør unngå dette da det har flere ulemper.

For det tredje kan vi åpne en ny økt og feste enheten på nytt for å hente relasjonene. Vi kan gjøre det ved å bruke slå sammen metode på økten.

Til slutt kan vi initialisere de nødvendige tilknytningene i forretningslagene. Vi vil diskutere dette i neste avsnitt.

7.2. Initialisering av relevante lat forhold i forretningslaget

Det er mange måter å initialisere late forhold på.

Et alternativ er å initialisere dem ved å påkalle de tilsvarende metodene på enheten. I dette tilfellet vil dvalemodus utstede flere databasespørsmål som forårsaker svekket ytelse. Vi refererer til det som “N + 1 SELECT” -problemet.

For det andre kan vi bruke Hent Bli med for å få dataene i ett enkelt spørsmål. Vi må imidlertid skrive tilpasset kode for å oppnå dette.

Endelig, vi kan bruke enhetsgrafer for å definere alle attributtene som skal hentes. Vi kan bruke kommentarene @NamedEntityGraph, @NamedAttributeNode, og @NamedEntitySubgraph å erklærende definere enhetsgrafen. Vi kan også definere dem programmatisk med JPA API. Deretter, vi henter hele grafen i en enkelt samtale ved å spesifisere den i hentingsoperasjonen.

8. Transaksjonsproblemer

Transaksjoner definerer arbeidsenheter og isolasjon mellom samtidige aktiviteter. Vi kan avgrense dem på to forskjellige måter. Først kan vi definere dem deklarativt ved å bruke merknader. For det andre kan vi administrere dem programmatisk ved hjelp av Hibernate Transaction API.

Videre delegerer dvalemodus transaksjonsledelsen til en transaksjonssjef. Hvis en transaksjon av en eller annen grunn ikke kunne startes, begås eller rulles tilbake, gir Hibernate et unntak.

Vi får vanligvis en TransactionException eller en IllegalArgumentException avhengig av transaksjonsleder.

Som en illustrasjon, la oss prøve å begå en transaksjon som er merket for tilbakeføring:

offentlig ugyldig givenTxnMarkedRollbackOnly_whenCommitted_thenTransactionException () {throw.expect (isA (TransactionException.class)); throw.expectMessage ("Transaksjonen var bare merket for tilbakeføring; kan ikke begå"); Øktøkt = null; Transaksjonstransaksjon = null; prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (15); product.setName ("Product1"); session.save (produkt); transaction.setRollbackOnly (); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); }}

Tilsvarende kan andre feil også forårsake et unntak:

  • Blanding av deklarative og programmatiske transaksjoner
  • Forsøker å starte en transaksjon når en annen allerede er aktiv i økten
  • Prøver å begå eller tilbakestille uten å starte en transaksjon
  • Prøver å foreta eller tilbakebetale en transaksjon flere ganger

9. Samtidige problemer

Dvalemodus støtter to låsingsstrategier for å forhindre databasekonsistens på grunn av samtidige transaksjoner - optimistisk og pessimistisk. Begge deler et unntak i tilfelle en låsende konflikt.

For å støtte høy samtidighet og høy skalerbarhet bruker vi vanligvis optimistisk samtidighetskontroll med versjonskontroll. Dette bruker versjonsnumre eller tidsstempler for å oppdage motstridende oppdateringer.

OptimisticLockingException kastes for å indikere en optimistisk låsekonflikt. For eksempel får vi denne feilen hvis vi utfører to oppdateringer eller slettinger av samme enhet uten å oppdatere den etter den første operasjonen:

offentlig ugyldig nårDeletingADeletedObject_thenOptimisticLockException () {throw.expect (isA (OptimisticLockException.class)); throw.expectMessage ("Batchoppdatering returnerte uventet radtall fra oppdatering"); kastet.expectCause (isA (StaleStateException.class)); Øktøkt = null; Transaksjonstransaksjon = null; prøv {session = sessionFactory.openSession (); transaksjon = session.beginTransaction (); Produktprodukt = nytt produkt (); product.setId (12); product.setName ("Produkt 12"); session.save (product1); transaction.commit (); session.close (); økt = sessionFactory.openSession (); transaksjon = session.beginTransaction (); produkt = session.get (Produkt.klasse, 12); session.createNativeQuery ("slett fra produkt der id = 12") .executeUpdate (); // Vi må oppdatere for å fikse feilen. // session.refresh (produkt); session.delete (produkt); transaction.commit (); } fange (Unntak e) {rollbackTransactionQuietly (transaksjon); kaste (e); } til slutt {closeSessionQuietly (økt); }}

På samme måte kan vi også få denne feilen hvis to brukere prøver å oppdatere den samme enheten nesten samtidig. I dette tilfellet kan det første lykkes, og det andre reiser denne feilen.

Derfor, vi kan ikke helt unngå denne feilen uten å innføre pessimistisk låsing. Vi kan imidlertid minimere sannsynligheten for at det oppstår ved å gjøre følgende:

  • Hold oppdateringsoperasjonene så korte som mulig
  • Oppdater representasjoner av enheter i klienten så ofte som mulig
  • Ikke cache enheten eller noe verdiobjekt som representerer den
  • Oppdater alltid enhetsrepresentasjonen på klienten etter oppdateringen

10. Konklusjon

I denne artikkelen så vi på noen vanlige unntak som oppstod under bruk av dvalemodus. Videre undersøkte vi sannsynlige årsaker og løsninger.

Som vanlig finner du full kildekode på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found