Slovník pojmů
Doctrine ORM: co řeší a kdy použít SQL přímo
ORM mapuje objekty na relační data. Nenahrazuje ale constrainty, transakce, indexy ani porozumění výslednému SQL.
Stručná definice
Práce s objekty nad relační databází.
Vývojář pracuje například s objektem objednávky, zákazníkem a položkami objednávky; Doctrine podle mapování čte a zapisuje tabulky, sloupce a vazby. ORM znamená object-relational mapper a pomáhá u běžných transakčních částí aplikace.
Entity nejsou automaticky doménovým modelem. V jednoduché aplikaci mohou být přiměřeně stejné, ve složitější doméně ale persistence požadavky jako ID, nullable sloupce a lazy kolekce nemusí patřit do čisté obchodní vrstvy.
Použití
Kde ORM ulehčuje práci
Doctrine ORM se osvědčuje tam, kde systém vytváří, mění a načítá propojená data.
- objednávky, zákazníci, produkty a položky objednávky
- uživatelé, role a oprávnění
- administrace, stavové procesy a reklamace
- ukládání výsledků importů a synchronizací
- běžná aplikační logika pracující s objekty a jejich vazbami
Praktický příklad
Marketplace objednávka a položky
Importní služba vyhledá objednávku podle externího ID. Pokud neexistuje, vytvoří objednávku, zákazníka podle pravidel systému a samostatné entity položek; pokud už existuje, aktualizuje jen údaje, které marketplace skutečně spravuje.
Databázový unikátní constraint na external_order_id chrání před souběhem dvou importů. Doctrine zapíše objednávku a položky v jedné transakční jednotce. Přehled obratu ale může použít jedno agregované SQL místo načtení celého objektového grafu.
Jak funguje
Od objektu ke změně v databázi
Doctrine nemění databázi při každém nastavení vlastnosti. Změny sleduje a zapíše ve vymezené jednotce práce.
- Načtení nebo vytvoření Aplikace získá či vytvoří entitu Order a její související objekty.
- Mapování Metadata určují tabulku, sloupce, typy hodnot a vlastnictví vztahů.
- Entity Manager Spravuje entity, načítání, plánování zápisu a komunikaci s databází.
- Unit of Work Sleduje nové, změněné a odstraněné objekty a určí nutné SQL příkazy.
- Flush a transakce Změny se zapíší v jasně zvolené transakční hranici, nebo se při chybě neprovedou.
Důležité vlastnosti
Pojmy, které ovlivňují správnost i výkon
Pohodlí ORM nesmí zakrýt, co skutečně dělá databáze.
Entity a mapování
Mapování popisuje primární klíč, typy i vztahy. Pokud má marketplace objednávka jedinečné externí ID, patří ochrana také do databázového unikátního constraintu.
Repository a vztahy
Repository má nést smysluplné dotazy. U položek objednávky s cenou a množstvím dává obvykle větší smysl samostatná entita než prostá many-to-many vazba.
Lazy loading a N+1
Vazba se může načíst až při použití. To šetří data, ale v seznamu může vytvořit N+1 dotazů. Oprava vychází z měření konkrétní obrazovky, ne ze slepého eager loadingu všeho.
Migrace, DBAL a SQL
Verzované migrace jsou bezpečnější než automatické dorovnávání schématu v produkci. DBAL a parametrizované SQL jsou přirozenou volbou pro reporty, agregace a specifické výkonnostní dotazy.
Volba nástroje
ORM, DBAL a přímý dotaz
Nejde o ideologickou volbu jedné vrstvy pro celou aplikaci.
- Doctrine ORM
- Práce s entitami, vztahy a běžnými změnami transakčního modelu.
- Doctrine DBAL
- Nižší vrstva pro připojení, parametrizované SQL, transakce a query builder.
- Přímé SQL
- Často čitelnější pro agregaci, report, dávkový import nebo databázově specifickou operaci.
- Databázový návrh
- Constrainty, indexy, transakce a tvar schématu zůstávají důležité bez ohledu na použitou PHP knihovnu.
Výhody a omezení
ORM nenahrazuje cenu databázových operací
Přínosy
- přirozená práce s propojenými daty v aplikační logice
- sjednocené mapování typů, vztahů a repository
- sledování změn a koordinovaný zápis objektů
- kombinace s DBAL a cíleným SQL podle konkrétní potřeby
Časté chyby
- serializace entit přímo do veřejného API a nechtěné načítání vazeb
- nepozorované N+1 dotazy a zbytečně velký Unit of Work
- volání flush po každé drobné změně bez transakčního záměru
- představa, že ORM automaticky vyřeší integritu a výkon databáze
Hranice použití
Entita není automaticky jediný model aplikace.
Pro stav objednávky, zákazníka a položek je ORM často čitelné. Pro přehled tržeb nad velkým objemem ale obvykle není nutné načítat tisíce entit — vhodnější může být jeden agregovaný SQL nebo DBAL dotaz, který vrátí jen potřebná čísla.
Oddělení doménového a persistence modelu má mít důvod v reálné složitosti. Vynucovat další vrstvy v jednoduché administraci nepomáhá, stejně jako skrývat náročný databázový dotaz za neurčitou abstrakci.
Na co myslet
Správná data mají přednost před pohodlným API
Kvalitní použití ORM propojuje aplikační kód s vědomým návrhem databáze.
- unikátní a referenční constrainty odpovídající business pravidlům
- jasné transakční hranice pro související změny
- měření SQL dotazů a cílené řešení N+1
- verzované, ověřené a zpětně kompatibilní migrace
- DTO či explicitní response model místo přímé serializace entit
Časté otázky
Co Doctrine ORM je a není
Je Doctrine ORM databáze?
Ne. Je to PHP knihovna pro práci s relační databází. Data mohou být například v PostgreSQL, MySQL nebo SQLite.
Musím přes Doctrine ORM psát všechny dotazy?
Ne. Vedle ORM lze použít Doctrine DBAL nebo přímo parametrizované SQL. Volba vychází z povahy dotazu a čitelnosti.
Je flush vhodné volat po každé změně?
Ne nutně. U běžného požadavku může být přirozené zapsat související změny najednou. U velkého importu je zase potřeba dávkovat práci a hlídat velikost Unit of Work.
Vyřeší ORM problém N+1 automaticky?
Ne. Lazy loading může N+1 naopak skrýt. Je nutné sledovat skutečné SQL a upravit načítání pro konkrétní případ použití.
Jak Doctrine ORM používám v praxi
Nejdřív řeším data, až potom nástroj.
Doctrine používám pro běžnou práci s relačními modely ve Symfony aplikacích. U specifických a výkonnostně citlivých dotazů volím cílené SQL.