Når man skaper komplekse applikasjoner, er det nesten uunngåelig at man må håndtere en database. Slike applikasjoner krever ofte implementering av CRUD-operasjoner, det vil si evnen til å opprette, lese, oppdatere og slette data.
For å håndtere dette trengs en database. Hvis applikasjonen er utviklet med et objektorientert programmeringsspråk som JavaScript, og man benytter en relasjonsdatabase som MySQL, kan det være utfordrende å administrere databasen.
Som JavaScript-utvikler må man i tillegg fokusere på detaljene i en relasjonsdatabase, forstå databasesyntaksen og konstruere komplekse SQL-spørringer som applikasjonen krever.
Det er viktig å huske at relasjonsdatabaser organiserer data i tabeller med rader og kolonner, mens JavaScript arbeider med objekter og relasjoner mellom dem. Denne forskjellen kan gjøre jobben tidkrevende og vanskelig, noe som understreker behovet for en Object Relational Mapper (ORM).
Object Relational Mapper (ORM)
En ORM er et verktøy som gjør det mulig for utviklere å jobbe med relasjonsdatabaser ved hjelp av objektorienterte prinsipper.
En ORM fungerer som et bindeledd mellom applikasjonskoden og den valgte relasjonsdatabasen, og lar utviklere arbeide med databasen på samme objektorienterte måte som i selve applikasjonskoden.
ORM-er tilordner relasjonsdatabasetabeller til klasser der klasseinstanser representerer oppføringer eller rader i tabellen. Klasseattributter benyttes for å representere kolonner i tabellen.
Dette betyr at utviklere kan bruke det valgte programmeringsspråket til å opprette, lese, oppdatere, slette og administrere data som er lagret i databasen uten å måtte skrive komplekse SQL-setninger.
Ved å benytte en ORM reduserer man behovet for å lese SQL, og man unngår også å lære et nytt spørringsspråk for å håndtere databasen.
For å illustrere hvordan en ORM fungerer, kan vi se på følgende MySQL-spørring for å hente ut brukere fra IT-avdelingen:
SELECT * FROM users WHERE department="IT";
Den samme spørringen kan utføres ved hjelp av en JavaScript ORM, som vist nedenfor. Her ser man hvordan vanlig JavaScript brukes for å gjøre samme forespørsel:
const users = await User.findAll({ where: { department: 'IT', }, });
Fordeler ved å bruke en ORM
Her er noen av fordelene JavaScript-utviklere kan oppnå ved å bruke en ORM:
Abstraksjon av databasekompleksitet
ORM-er skjuler kompleksiteten i den underliggende databasen, og lar utviklere samhandle med databasen via backend-språket i stedet for kompleks SQL.
Enkelte ORM-er tilbyr også spørringsbyggere, som gjør det enkelt å skrive komplekse spørringer ved hjelp av OOP-prinsipper. Dette gjør det mulig for utviklere å skrive renere, mer vedlikeholdbar kode som er enklere å feilsøke og oppdatere.
Økt produktivitet
ORM-er abstraherer kompleksiteten ved å skrive rå SQL-spørringer og administrere databaseinteraksjoner, og lar utviklere fokusere på forretningslogikken til applikasjonen, som er den viktigste delen.
Utviklere samhandler med databaser ved hjelp av et mer kjent OOP-mønster uten å skrive mye standardkode eller utføre repeterende oppgaver.
ORM-er kan også brukes til å automatisk fylle databaser og generere datatilgangskoder. Dette øker utviklernes produktivitet betydelig.
Databaseagnostisisme
En sentral funksjon ved ORM-er er at de gir muligheten til å skrive applikasjonskoden på en måte som ikke er avhengig av en spesifikk database. Dette gjør det enkelt å bytte database uten å måtte endre store deler av applikasjonskoden.
Dette er spesielt viktig når en applikasjon trenger å utvikle seg eller støtte bruk av flere databaser.
Enkelt skjema- og relasjonsadministrasjon
ORM-er forenkler prosessen med å jobbe med databasens skjema og administrere relasjoner mellom databaseenheter.
Enkelte ORM-er tilbyr funksjoner som automatisk skjemagenerering fra eksisterende databaser, og de fleste tilbyr metoder for å enkelt definere og administrere relasjoner mellom tabeller i databasen.
Forbedret sikkerhet
ORM gir forbedret databasesikkerhet ved å filtrere data og bruke parameteriserte spørringer internt. Parameteriserte spørringer benytter plassholdere for inngangsverdier i stedet for å bruke direkte brukerinput i SQL-spørringene.
Dermed blir ikke brukerinput direkte integrert i en SQL-spørring. Dette gjør at ORM-en kan beskytte applikasjonen mot SQL-injeksjonsangrep og dermed øke applikasjonens sikkerhet.
Ulemper ved å bruke en ORM
Selv om ORM-er har mange fordeler, er det også noen ulemper knyttet til bruken av dem. Siden de introduserer et abstraksjonslag over databasen, kan det føre til ytelsesproblemer og høyere minneforbruk.
For å bruke en ORM må utviklere dessuten lære å bruke den, og de bør ha en grunnleggende forståelse av SQL for å vite hva de ulike kommandoene faktisk gjør.
Til tross for disse ulempene, er ORM-er fortsatt et svært nyttig verktøy for utviklere og den enkleste måten å samhandle med relasjonsdatabaser fra applikasjoner bygget med OOP-prinsipper. For å komme i gang med å bruke en ORM, er her noen av de beste ORM-ene man kan bruke i JavaScript-applikasjoner:
Sequelize
Ifølge den offisielle dokumentasjonen er Sequelize en moderne TypeScript og Node.js ORM for Oracle DB, PostgreSQL, MySQL, MariaDB, SQLite, Microsoft SQL Server, IBM DB2 og Snowflake-database. Sequelize er en åpen kildekode og en veldig populær ORM for utviklere som arbeider med Node.js-rammeverket og relasjonsdatabaser.
Dette skyldes dens robuste sett med funksjoner som gjør arbeidet med relasjonsdatabaser i Node.js enkelt. For det første er Sequelize en løftebasert ORM, en funksjon som gjør at den støtter løfter som er en sentral funksjon i Node.js-rammeverket.
I tillegg støtter Sequelize «eager loading», hvor ressurser lastes umiddelbart når applikasjonskoden utføres, og «lazy loading», hvor ressurser ikke lastes inn før de er nødvendige. Sequelize har også solid transaksjonsstøtte, lesereplikering og modellvalidering, og den tillater databasemigrering og synkronisering.
Brukere kan også definere assosiasjoner og relasjoner mellom moduser når de bruker Sequelize. I tillegg gir det et rikt sett med spørringsalternativer, som lar utviklere konstruere komplekse databasespørringer med letthet.
Prisma
Prisma er en åpen kildekode-ORM som lar deg enkelt administrere og samhandle med databasen din fra et hvilket som helst JavaScript- eller TypeScript-miljø.
Prisma støtter PostgreSQL, MySQL, Microsoft SQL Server, CockroachDB, SQLite og MongoDB. I tillegg tillater den enkel integrasjon med alle JavaScript- eller TypeScript-rammeverk, forenkler databaser og øker typesikkerheten.
For å hjelpe utviklere med å bygge spørringer, har Prisma en funksjon kalt Prisma-klient som kommer med autofullføring og lar utviklere bygge typesikre spørringer som er tilpasset skjemaet de bruker i applikasjonen.
Utviklere kan lage sitt eget skjema fra bunnen av eller bruke Prisma til å autogenerere skjemaer ved å introspektere en eksisterende database.
En annen Prisma-funksjon er Prisma migrate, et verktøy for migrering av Prisma-skjemaer som automatisk genererer tilpassbare SQL-migreringer, og som lar brukere ha full kontroll og fleksibilitet når de tar applikasjonene sine fra utvikling til produksjon.
Til slutt har Prisma-brukere tilgang til Prisma Studio, et admin-brukergrensesnitt som lar brukere se, utforske, manipulere og forstå dataene som er lagret i databasen deres. Alle disse funksjonene gjør Prisma til en utmerket ORM for JavaScript- og TypeScript-utviklere.
TypeORM
TypeORM er en åpen kildekode ORM som ble utviklet for å alltid støtte de nyeste JavaScript-funksjonene og tilby tilleggsfunksjoner som gjør det mulig for utviklere å lage alle typer applikasjoner som bruker databaser.
TypeORM støtter MySQL, MariaDB, PostgreSQL, CockroachDB, SQLite, Microsoft SQL Server, Oracle, SAP Hana og sql.js-databaser.
TypeORM støtter JavaScript og TypeScript, og også MongoDB, som ikke er en relasjonsdatabase. TypeORM fungerer i Node.js, en nettleser, Ionic, Cordova, React Native, NativeScript, Expo og Election-plattformer.
TypeORM lar utviklere jobbe med flere databasetyper og bruke flere databaseforekomster. Den støtter bufring, logging, transaksjoner, assosiasjoner, «eager» og «lazy» relasjoner og muliggjør migreringer og automatisk migrering.
TypeORM støtter også DataMapper, ActiveRecord, strømming av råresultater, spørringer på tvers av databaser og skjemaer og tilbyr brukere en kraftig spørringsbygger.
MikroORM
MikroORM er en åpen kildekode TypeScript ORM som støtter MySQL, MariaDB, PostgreSQL, SQLite og MongoDB. Denne ORM-en er basert på Datamapper, Identity Map Pattern og Unit of Work. En arbeidsenhet brukes til å vedlikeholde en liste over enheter som er berørt av en forretningstransaksjon, og den koordinerer også skriving av endringene.
Dette gir den fordelen at den tillater automatisk håndtering av transaksjoner, automatisk gruppering av alle forespørsler og direkte implementering av forretnings-/domenelogikk direkte i de brukte enhetene.
MikroORM kommer også med en metadata-bevisst QueryBuilder med støtte for automatisk sammenføyning, og et hendelsessystem som kan brukes til å koble seg inn i enhetens livssyklus, og som også endrer hvordan UnitOfWork fungerer.
Oppfylling av databaser, det vil si å fylle en database med et innledende sett med data, er også enklere med MikroORM, siden den kommer med en «seeder» som lar deg generere falske data av et hvilket som helst volum eller format, og bruke det til å fylle databasen din.
Til slutt støtter MikroORM også enkle opp-og-ned databasemigreringer.
Bookshelf.js
Bookshelf er en åpen kildekode JavaScript ORM for Node.js. Denne ORM-en har som mål å tilby et enkelt bibliotek som kan brukes til å utføre vanlige oppgaver når man spør etter databaser i JavaScript, og som danner relasjoner mellom objekter. Bookshelf er designet for å fungere med PostgreSQL, MySQL og SQLite3.
Som en Node.js ORM, støtter Bookshelf bruken av løfter og tradisjonelle tilbakeringninger når man arbeider med ORM-en fra en Node.js-applikasjon. I tillegg støtter den transaksjoner, polymorfe assosiasjoner, «eager» og «nested eager» relasjonsinnlasting og en rekke relasjoner.
Selv om den ikke har like mange funksjoner som enkelte andre ORM-er, utmerker Bookshelf seg med sin enkelhet, fleksibilitet og hvor lett det er å lese, forstå kodebasen og utvide den. Hvis du trenger en enkel og lett ORM for dine JavaScript-prosjekter, er Bookshelf et godt valg.
Node ORM2
Node ORM2 er en enkel og lett Node.js ORM som støtter MySQL, SQLite og Progress OpenEdge-databaser. Denne ORM-en gjør det enkelt å jobbe med modellene dine i Node.js. Når du jobber med modeller, lar den deg enkelt opprette, synkronisere, slette, hente, finne, fjerne, telle og også lage datamodeller i stor skala.
Den tillater også opprettelse av assosiasjoner mellom modeller og definering av tilpassede valideringer i tillegg til de innebygde valideringene som følger med. Node ORM2 implementerer «singleton-atferd», som sikrer at når du henter den samme raden flere ganger, får du alltid det samme objektet som representerer den raden.
Waterline
Waterline er en adapterbasert ORM for Node.js. Det er også standard ORM som følger med Sails-nettutviklingsrammeverket. Waterline kan imidlertid fortsatt brukes uten å bruke Sails-rammeverket.
Som en adapterbasert ORM gir Waterline støtte for å arbeide med flere databasesystemer ved bruk av adaptere. Offisielt støttede databaser inkluderer MySQL, PostgreSQL, MongoDB, Redis og lokal lagring.
Waterline har imidlertid også fellesskapsadaptere for CouchDB, SQLite, Oracle, Microsoft SQL Server, DB2, Riak, neo4j, OrientDB, Amazon RDS, DynamoDB, Azure Tables, RethinkDB og Solr.
Waterline lar deg bruke mer enn én database i prosjektet, og det gir et enhetlig API for å jobbe med forskjellige databaser og protokoller. Dette betyr at kode skrevet med Waterline ORM kan fungere med alle databaser som støttes av ORM uten å måtte endre koden.
Waterline er laget med vekt på modularitet, testbarhet og konsistens på tvers av adaptere, noe som gjør den enkel å bruke og integrere med en rekke databaser.
Objection.js
Objection.js er en ORM som tar sikte på å holde deg unna og gjøre det enkelt å bruke den fulle kraften i SQL og den underliggende databasemotoren.
Den tilbyr alle fordelene til en SQL-spørringsbygger og er kraftig for å hjelpe deg med å jobbe med relasjoner. En SQL-spørringsbygger er et verktøy som forenkler prosessen med å lage komplekse SQL-spørringer.
Objection.js tilbyr en enkel måte å definere modeller og relasjoner mellom dem, med fulle funksjoner for å opprette, lese, oppdatere og slette (CRUD) som utnytter den fulle kraften til SQL, i tillegg til å tilby enkle å bruke transaksjoner.
Brukere kan også «eager loade», sette inn og sette opp objektgrafer, lagre komplekse dokumenter som enkeltrader og bruke JSON-skjemavalidering. Objection.js har offisiell støtte for TypeScript og JavaScript.
Konklusjon
Som utvikler, når man jobber med relasjonsdatabaser fra en JavaScript- eller TypeScript-applikasjon, er det en god idé å samhandle med databasen via en ORM.
Dette vil ikke bare forenkle databaseinteraksjonene, men også øke produktiviteten, redusere mengden SQL du må skrive og forbedre sikkerheten til applikasjonen.
Når du skal velge en ORM, bør du vurdere en av de ORM-ene som er fremhevet i artikkelen, avhengig av hvilke funksjoner som passer best for applikasjonen du utvikler.
Du kan også utforske de beste JavaScript-kompilatorene på nettet.