Kas yra ORM? Kaip programos bendrauja su duomenų bazėmis, paaiškinta
ORM (objektinis-reliacinis susiejimas, angl. object-relational mapper) yra kodo biblioteka, kuri stovi tarp programos ir reliacinės duomenų bazės. Vietoj SQL užklausų rašymo kūrėjai dirba su duomenimis kaip įprastais objektais savo programavimo kalba – pavyzdžiui, db.booking.create(...) arba Booking.find(...) – o ORM tai paverčia SQL, paleidžia ją ir rezultatus vėl paverčia objektais. Populiarūs pavyzdžiai: Prisma ir Drizzle TypeScript kalbai, SQLAlchemy Python kalbai ir Entity Framework Core C# kalbai.
Kodėl ORM svarbūs kuriant su dirbtiniu intelektu
Kai DI programų kūrimo įrankis prideda prie jūsų programos duomenų bazę, jis paprastai kartu prideda ir ORM, kuris su ja bendrauja. ORM kodo rašyti jums nereikės, bet verta žinoti, kad jis ten yra:
- Duomenų modelis gyvena kode. ORM schemos failas dažnai yra aiškiausias jūsų programos duomenų aprašymas: kokios yra lentelės, kokie laukai jose yra ir kaip jos susijusios. Jį perskaityti – greitas būdas patikrinti, ar DI suprato jūsų programą.
- Pakeitimai duomenų bazėje vyksta per migracijas. Kai prašote „pridėti telefono numerį klientams“, DI atnaujina modelį ir sukuria migraciją. Tai žinant lengviau suprasti, kodėl pakeitimas gali reikalauti pritaikymo, kad veiktų tiesiogiai.
- Saugumas pagal numatymą. ORM sudaro užklausas taip, kad apsaugotų nuo SQL injekcijos – vienos dažniausių saugumo spragų programose, kuriose užklausos surenkamos rankiniu būdu.
- Greičio spąstai. ORM lengva netyčia paleisti šimtus mažų užklausų ten, kur pakaktų vienos. Tai dažna DI sukurtų programų puslapių lėtumo priežastis.
Kasdienis palyginimas
Įsivaizduokite britą keliautoją ir japonų parduotuvininką, kurie nekalba viena kalba ir bendrauja per vertėją.
Keliautojas (jūsų programa) sako: „Noriu trijų pigiausių arbatų, kurias turite.“ Vertėjas (ORM) tai išverčia į tikslią japonų kalbą (SQL), perduoda parduotuvininkui (duomenų bazei) ir atsakymą išverčia atgal į anglų kalbą.
Keliautojas niekada nesimoko japonų kalbos, ir daugeliui pokalbių to pakanka. Tačiau sudėtingoms derybomis gali prireikti kalbėti tiesiogiai – todėl dauguma ORM leidžia prireikus rašyti gryną SQL.
Kaip veikia ORM
Duomenų bazės, pavyzdžiui Postgres, saugo duomenis lentelėse iš eilučių ir stulpelių ir yra užklausiamos naudojant SQL. Programavimo kalbos dirba su objektais: rezervacija, turinti date, customer ir status. ORM tarp jų atlieka susiejimą:
| Duomenų bazės pusė | ORM / kodo pusė |
|---|---|
Lentelė bookings | Modelis Booking |
| Eilutė | Vienas rezervacijos objektas |
Stulpelis starts_at | Laukas startsAt |
Užsienio raktas customer_id | Ryšys booking.customer |
SELECT, INSERT, UPDATE, DELETE | find, create, update, delete metodai |
Šios keturios operacijos yra CRUD veiksmai, ant kurių stovi beveik kiekviena programa.
Darbinis pavyzdys: rezervacijos su Prisma
Štai supaprastinta Prisma schema grožio salono rezervacijų programai. Ji aprašo dvi lenteles ir tai, kaip jos susietos:
model Customer {
id Int @id @default(autoincrement())
name String
email String @unique
bookings Booking[]
}
model Booking {
id Int @id @default(autoincrement())
startsAt DateTime
service String
customer Customer @relation(fields: [customerId], references: [id])
customerId Int
}
Paprastais žodžiais: klientas turi vardą, unikalų el. pašto adresą ir daug rezervacijų; kiekviena rezervacija turi pradžios laiką, paslaugą ir priklauso vienam klientui.
Dabar programai reikia: „Lenos artimiausios rezervacijos, pirmiausia ankstesnės“:
const bookings = await db.booking.findMany({
where: {
customer: { email: "lena@example.com" },
startsAt: { gte: new Date() },
},
orderBy: { startsAt: "asc" },
});
ORM tai paverčia maždaug tokia SQL, ją paleidžia ir grąžina rezervacijų objektų sąrašą:
SELECT b.* FROM "Booking" b
JOIN "Customer" c ON c.id = b."customerId"
WHERE c.email = $1 AND b."startsAt" >= $2
ORDER BY b."startsAt" ASC;
$1 ir $2 yra vietos rezervuoti: el. paštas ir data siunčiami atskirai nuo užklausos teksto, o tai ir apsaugo nuo SQL injekcijos.
Migracijos
Jei tada paprašote „leisti klientams pridėti telefono numerį“, DI pridės phone String? prie Customer modelio (? reiškia, kad laukas neprivalomas) ir sugeneruos migraciją – nedidelį SQL scenarijų, pavyzdžiui ALTER TABLE "Customer" ADD COLUMN "phone" TEXT;. Migracijos išsaugomos eilės tvarka, todėl kiekviena duomenų bazės kopija gali būti atnaujinta iki tos pačios struktūros, o pakeitimų istorija išlieka.
Dažniausi ORM pagal kalbą
| Kalba | Dažniausi ORM |
|---|---|
| TypeScript / JavaScript | Prisma, Drizzle, TypeORM, Sequelize |
| Python | SQLAlchemy, Django ORM, SQLModel |
| C# | Entity Framework Core |
| Java | Hibernate (dažnai per Spring Data JPA) |
| Ruby | Active Record |
ORM skiriasi tuo, kiek jie paslepia SQL. Prisma naudoja savo schemos kalbą ir užklausų stilių; Drizzle tyčia išlieka arti SQL struktūros, kartu viską palaikydamas tipizuotą. Lengvesni įrankiai, vadinami užklausų kūrikliais (query builder), pavyzdžiui Knex arba Kysely TypeScript kalbai, padeda kurti SQL kode, bet nesusieja eilučių su pilnais objektais.
Pagrindinės sąvokos
| Terminas | Reikšmė |
|---|---|
| Modelis | Lentelės ir jos laukų aprašymas kode. |
| Schema | Visų lentelių, laukų ir ryšių pilnas aprašymas. |
| Ryšys | Ryšys tarp modelių, pavyzdžiui rezervacija priklauso klientui. |
| Migracija | Versijuotas scenarijus, keičiantis duomenų bazės struktūrą. |
| Užklausų kūrikliai | Lengvesnis įrankis SQL kurti kode be pilno objektų susiejimo. |
| N+1 problema | Viena užklausa sąrašui, po vieną kiekvienam elementui – lėta, kai duomenų daug. |
| Gryna SQL | Rankiniu būdu parašytas SQL, naudojamas tada, kai ORM trukdo. |
Dažnos klaidingos nuomonės
- „ORM yra duomenų bazė.“ Ne. Tai vertėjas. Vis tiek reikia duomenų bazės, pavyzdžiui Postgres.
- „Su ORM nereikia suprasti savo duomenų.“ Prastai suprojektuotos lentelės vargina ir per ORM. Geras duomenų modelis svarbesnis nei įrankis.
- „ORM visada lėti.“ Įprastos užklausos veikia gerai. Lėtumas dažniausiai kyla dėl N+1 užklausų ar trūkstamų indeksų, o tai ištaisoma.
- „ORM reiškia, kad SQL injekcijos rizikos niekada nebus.“ Standartiniai ORM metodai saugūs, bet gryna SQL, į kurią įklijuojami vartotojo duomenys, vis tiek pavojinga.
- „Schemos failo redagavimas pakeičia gyvą duomenų bazę.“ Tik tada, kai sukuriama migracija ir ji pritaikoma tai duomenų bazei.
Ko klausti savo DI kūrimo įrankio
- „Parodyk duomenų bazės schemą ir paaiškink kiekvieną lentelę bei ryšį paprasta kalba.“
- „Kurį ORM naudoja šis projektas ir kur yra migracijos?“
- „Prieš keisdamas bet kurią lentelę, pasakyk, ar bus paveikti esami duomenys, ir niekada nepanaikink stulpelio su duomenimis neklausęs.“
- „Patikrink lėčiausius puslapius dėl N+1 užklausų ir pridėk indeksus ten, kur sąrašai filtruojami ar rūšiuojami.“
- „Įsitikink, kad kiekviena užklausa, naudojanti vartotojo įvestį, eina per ORM arba naudoja parametrus – jokio SQL, surinkto iš eilučių.“
ORM Mythex platformoje
Kai programai reikia išsaugoti duomenis, Mythex prie projekto prideda atskirą Postgres duomenų bazę – paklauskite pokalbyje arba naudokite /database komandą – ir įrašo jos prisijungimo duomenis į darbo aplinką bei publikuotą programą (Duomenų bazė). Tada agentas parašo kodą, kuris skaito ir įrašo jūsų duomenis. Jei turite pageidavimą – „naudok Prisma“, „naudok SQLAlchemy“ ar „gryna SQL, be ORM“ – pasakykite pokalbyje. Kada norite patikrinti struktūrą, paprašykite agento ją paaiškinti; failus galite peržiūrėti kodo redaktoriuje. Platesnį vaizdą rasite kas yra duomenų bazė ir SQL vs NoSQL.
Klausimai
Kas yra ORM paprastais žodžiais?
ORM (objektinis-reliacinis susiejimas) yra kodo biblioteka, esanti tarp programos ir reliacinės duomenų bazės. Ji leidžia kūrėjams skaityti ir įrašyti duomenis kaip įprastus objektus savo programavimo kalba, o SQL užklausas už scenos parašo pati.
Kokie yra ORM pavyzdžiai?
Dažniausi ORM – Prisma ir Drizzle TypeScript bei JavaScript kalboms, SQLAlchemy ir Django ORM Python kalbai, Entity Framework Core C# kalbai, Hibernate Java kalbai ir Active Record Ruby on Rails.
Ar ORM geresnis nei rašyti SQL?
Tai priklauso nuo užduoties. ORM kasdienius skaitymus ir įrašymus padaro greitesnius rašyti, saugesnius ir lengviau keičiamus, o rankiniu būdu rašytas SQL suteikia visišką kontrolę sudėtingoms ataskaitoms ar našumui kritiškoms užklausoms. Dauguma ORM leidžia prireikus nusileisti iki gryno SQL.
Kas yra migracija?
Migracija yra nedidelis, versijuotas scenarijus, keičiantis duomenų bazės struktūrą, pavyzdžiui pridedantis lentelę ar stulpelį. ORM gali generuoti migracijas iš jūsų duomenų modelio, todėl kiekviena duomenų bazės kopija – nešiojamajame kompiuteryje, testavime ir produkcijoje – įgauna tą pačią struktūrą.