Devel.cz Lupa Měšec Podnikatel Root Zdroják.cz DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Názory k článku
Doctrine 2: základní definice entit

blizzboz
blizzboz (neregistrovaný) ---.95-103-13.t-com.sk
4. 8. 2010 3:52 Nový

otázka

celé vlákno

Keď už pracujeme s objektami, neni lepšie použiť nejakú objektovú databázu? Ja sám používam ORM (Entity Framework) ale ajtak nerozumiem v čom je použitie RDBMS + ORM frameworku lepšie ako priamo použitie ODBMS?

Václav Novotný
4. 8. 2010 9:38 Nový

Re: otázka

celé vlákno
Na tuto otázku není vůbec jednoduchá odpověď. Sám za sebe tvrdím, že pokud máme objektový model, tak určitě není automatické, že ho budeme ukládat do objektové databáze. Já osobně sahám po relační databázi z těchto důvodů:
  1. Větší zkušenost a více znalostí relačních databází
  2. Jednoduchost na správu a dostupnost (i když ta jednoduchost pramení právě z větších znalostí)
  3. Možnost dekompozice objektů do relací. Často je to nevýhoda, ale občas to může být výhoda
Určitě jsem na něco ještě zapomněl, ale jen tyto důvody mě drží u relačních databází. Pokud máme dobré ORM, což Doctrine 2 s přivřeným okem je, je rozhodování ještě jednodušší.
Patrik Votoček (Vrtak-CZ) aura:23
4. 8. 2010 4:03 Nový

BUG v ukázce

celé vlákno

v ukázce ukládání článků se uloží jenom první… Protože ten druhý není přidán do UnitOfWorku schází tam $entityManager->persist($anotherArticle); před flush.

Ondrej Mirtes
Ondrej Mirtes (neregistrovaný) 82.208.57.---
4. 8. 2010 8:07 Nový

Re: BUG v ukázce

celé vlákno

Je to takhle spravne, na entite se vola persist jen jednou, pak uz se ulozi jen pomoci flush().

Jan Tichý aura:21
4. 8. 2010 9:30 Nový

Re: BUG v ukázce

celé vlákno

Je to skutečně tak, jak píše Ondra výše – persist() se musí volat jen na úplně nově vytvořené entity. Od toho okamžiku už je entita trvale pod dohledem EntityManageru, a to i pokud ji získáme v nějakém jiném requestu přes find(). Takže při jakékoliv další změně se už nemusí persist() volat, EntityManager sám automaticky zajistí, že se všechny provedené změny zařadí do fronty v UnitOfWork a při nejbližším zavolání flush() pak trvale uloží i do databáze. Tak je tomu až do té doby, než entitu smažu či odepnu z EntityManageru.

Každopádně podrobnější debatu nad fungováním EntityManageru a UnitOfWork navrhuji nechat až pod článek, který se jimi bude zabývat podrobněji.

Jan Dolecek aura:45
4. 8. 2010 17:55 Nový

Efeknivnost

celé vlákno

Jak Doctrine pozna, ktere zaznamy se zmenily a tzn. ktere musi ulozit do DB?
Jde mi o to, ze treba nactu tisic zaznamu pomoci find(), na par z nich udelam nejakou malou zmenu a pak zavolam flush(). Bude Doctrine fungovat efektivne?
A jeste by me zajimalo, je mozne udelat nejaky hook, aby mi Doctrine logovalo veskere provedene zmeny (kdo, kdy, puvodni data, nova data)?
Diky za rady

Václav Novotný
4. 8. 2010 21:11 Nový

Re: Efeknivnost

celé vlákno

Jak Doctrine pozna, ktere zaznamy se zmenily a tzn. ktere musi ulozit do DB? Jde mi o to, ze treba nactu tisic zaznamu pomoci find(), na par z nich udelam nejakou malou zmenu a pak zavolam flush(). Bude Doctrine fungovat efektivne?

V rámci možností to efektivně funguje. Začíná to již při načítání entit. Pro každou načítanou entitu se pomocí funkce spl_object_hash() spočítá hash, který se uloží do interního pole v Unit of Work. Jakmile zavoláme flush na Entity Manageru, zavolá Entity Manager Unit of Work, aby zařídil uložení dat. Unit of Work projde každou načtenou entitu, spočítá pro ní další hash a porovná ho s hodnotou uloženou při načtení entity. Pokud se hodnoty nerovnají, ví, že se entita změnila. Aby byla práce ještě efektivnější, počítá si ještě pro každou entitu set změn, které pak pošle do databáze (což opět nejakým způsobem opimalizuje).

A jeste by me zajimalo, je mozne udelat nejaky hook, aby mi Doctrine logovalo veskere provedene zmeny (kdo, kdy, puvodni data, nova data)?

Toto udělat lze. V Doctrine2 se to realizuje pomocí listenerů. Honza jim určitě v některém díle bude věnovat pozornost, takže sem dám pouze odkaz do dokumentace: http://www.doctrine-project.org/projects/orm/2.0/docs/reference/events/en#implementing-event-listeners

Některé další implementace listenerů pak ukázal Benjamin Eberlei na Doctrine blogu:

  • http://www.doctrine-project.org/blog/doc­trine2-behaviours-nutshell?id=136
  • http://www.doctrine-project.org/blog/doc­trine2-versionable?id=138
paranoiq
paranoiq (neregistrovaný) 195.70.148.---
9. 9. 2010 16:37 Nový

Re: spl_object_hash() není hash!

celé vlákno

spl_object_hash() není hash! tato funkce nic nepočítá. pouze vrací jednoznačný identifikátor objektu. při změně vlastností objektu se hodnota vrácená spl_object_hash() nemění.
tato hodnota je použita pouze k indexaci polí entit a polí původních hodnot, aby je bylo možné navzájem dohledat a porovnat i pokud dojde ke změně všech údajů entity
_______
porovnávat entity s původní hodnotou musí složitěji (u private a protected nejspíš pomocí odemykání metodou setAccessible() z Reflection nebo konverzí objektu na pole)

Václav Novotný
9. 9. 2010 16:52 Nový

Re: spl_object_hash() není hash!

celé vlákno

Aha, už to vidím, díky za opravu.

Patrik Votoček (Vrtak-CZ) aura:23
5. 8. 2010 2:37 Nový

Re: BUG v ukázce

celé vlákno

Ha super já to pro jistotu vždy explicitně persistoval. A navíc jsem díky tomu konečně pochopil smysl  $em->detach($entity);

Václav Novotný
4. 8. 2010 9:41 Nový

Dobrý článek

celé vlákno

Dobrý článek Honzo. Hlavně úvod se mi líbí, protože lehce přesahuje tématiku ORM a ukazuje přístup, jak stavět doménové objekty, které jsou izolované od persistentní vrstvy aplikace.

jos
jos (neregistrovaný) ---.tabor.telecom.cz
4. 8. 2010 11:21 Nový

myšlenkový posun

celé vlákno

Typickým příkladem jsou cizí klíče. Ve skutečném světě nic takového jako cizí klíč není. Článek je prostě zařazen do nějaké kategorie. To, že se to v relačních databázích řeší nějakým cizím klíčem category_id v tabulce article, je jenom vedlejší efekt toho, jak relační databáze fungují.


Asi by se slušelo říct, že je to kvůli referenční integritě a že to programátor dělá hlavně proto, aby mu databáze nelhala (protože tam strčil / nechal strčit nesmysly). To s tim vedlejším efektem sem buď nepochopil, nebo je to úplnej nesmysl.
Nevim o SQL databázi, která by mi zakázala joinovat přes atributy jen proto, že mezi nima není cizí klíč


Jinak k tomu myšlenkovýmu posunu – programátor by se měl v případě cizích klíčů posunout spíš k uvažování o „doméně“ atributu relace. Mějme relaci A s atributem FOO (jehož hodnoty jsou z množiny přirozených čísel) a v ní dva řádky s hodnotama 1 a 2. Dále mějme relaci B s atributem BAR o němž prohlásíme, že je z domény (je datovýho typu) A.FOO a o přirozených číslech se v tomhle případě dále nebavíme


Bohužel současný produkty nenabízejí takhle přímočarý vyjádření … (nebo jo?)


A vůbec všechny SQL databáze dělají z programátora otroka a Doctrine mi nepřipadá jako elegantní způsob jak se z toho vymanit

Jan Tichý aura:21
4. 8. 2010 12:49 Nový

Re: myšlenkový posun

celé vlákno

Asi by se slušelo říct, že je to kvůli referenční integritě a že to programátor dělá hlavně proto, aby mu databáze nelhala (protože tam strčil / nechal strčit nesmysly).

Snažil jsem se tím říct víceméně to samé, co pak o něco dále píšete sám. Prostě v relačních databázích musím explicitně evidovat, přiřazovat a číst ID odkazovaného záznamu, takže článek přiřadím do kategorie číslo 3 tak, že přiřadím  article.category_id = 3.

Což je ale úplně špatné vnímání pokřivené specifiky relačních databází. Při práci s Doctrine 2 je potřeba právě myslet doménově a nezatěžovat se nějakými cizíma IDčkama. Takže přiřazení článku do kategorie se děje (schematicky vyjádřeno) napřiklad jako article.category = category, případně category.articles[] = article. Prostě žádná IDčka, žádné cizí klíče, nic takového.

Patrik Votoček (Vrtak-CZ) aura:23
5. 8. 2010 2:34 Nový

Re: myšlenkový posun

celé vlákno

Tohle chápu a líbí se mi. Ale jak řešíš právě avizovaný případ přiřazení kategorie k článku. Mám selectbox a se seznamem kategorií a jako nejvhodnější mě připadá pro value použít ID kategorie. Jenže pak obcházím právě onu Doménovou logiku (nebo mě to tak alespoň připadá).

Jan Tichý aura:21
5. 8. 2010 8:44 Nový

Re: myšlenkový posun

celé vlákno

Mícháš tu dohromady model a view. Na straně modelu se žádná doménová logika neobchází, protože prostě uděláš $article->setCategory($category) respektive $category->addArticle($article) a je to naprosto čisté.

Jiná věc jsou samozřejmě selectboxy, do kterých musíš cpát nějaké skalární veličiny, které jsou schopné mi jednoznačně identifikovat danou kategorii, a pro ten případ se pak samozřejmě hodí nejlépe IDčko. A pak po odeslání formuláře se samozřejmě v controlleru/pre­senteru udělá něco jako $article = $em->find('Article', $articleId); $category = $em->find('Category', $categoryId);. Ale to se děje ze specifických důvodů a někde úplně jinde, než v modelu – tedy ve view a controlleru/pre­senteru. Model je prostě i nadále čistě doménový.

Jan Dolecek aura:45
5. 8. 2010 13:45 Nový

Re: myšlenkový posun

celé vlákno

Doctrine cloveka nuti nejdriv ta data vytahnout z databaze, a pak tam zapsat upravu. Takze na takovou jednoduchou cinnost ti driv stacil jeden update, ale kluvi Doctrine se budou muset udelat jeste 2 selecty.
Toto se mi zda takove „divne“ a porad mi to nejde do hlavy. A navic se bojim poklesu vykonu aplikace kvuli takovymto zbytecnym operacim. Odhaduju, ze to ale zase nebude az takovy problem, ze?

Václav Novotný
5. 8. 2010 13:58 Nový

Re: myšlenkový posun

celé vlákno

Výkonový pokles tu samozřejmě je. To není problém jen Doctrine2, ale jakéhokoliv ORM. ORM se na oplátku snaží poskytnou komfort v mapování.

Nicméně je zde možnost, jak nenatahovat všechny entity, ale napsat si UPDATE ručně. Nepoužívá se na to čisté SQL, nýbrž DQL (Doctrine Query Language), které stále pracuje s entitami a jejich atributy. Takováhle aktualizace skrz DQL může být pak vložena do vlastního repozitáře konkrétní entity (např. nějaký ArticleRepository), který bude mít kupříkladu metodu ArticleReposi­tory::acceptA­llArticlesByDa­te(DateTime $date).

Jak se píše UPDATE v DQL je v dokumentaci v sekci UPDATE queries

Pavel
Pavel (neregistrovaný) ---.net.upcbroadband.cz
16. 8. 2010 16:13 Nový

Re: myšlenkový posun

celé vlákno

Nešlo by vytvořit neúplný objekt Article, který by se teprve při přístupu k jeho atributům inicializoval? Tuším by to mohl být návrhový vzor Decorator.

Jan Tichý aura:21
16. 8. 2010 18:51 Nový

Re: myšlenkový posun

celé vlákno

Rozhodně šlo. V Doctrine 2 se takovým neúplným objektům říká proxy a jsou využívané právě pro pozdní načítání dat jednotlivých entit. Určitě se k nim ještě v některém z příštích dílů seriálu podrobněji dostaneme.

Patrik Votoček (Vrtak-CZ) aura:23
5. 8. 2010 2:48 Nový

NEescapovaní názvů entity (tabulky) a sloupců

celé vlákno

Já vím že celkem spamuju ale…
Na to neescapování jsem nadával cca před týdnem. Vůbec to nechápu ale je k tomu tady ISSUE kterou jsem taky nepochopil. Nicméně myslím si že pokud se „zbouří“ dostatek lidí mohlo by to „borce“ od Doctrine donutit to vyřešit lépe…

Patrik Votoček (Vrtak-CZ) aura:23
5. 8. 2010 2:49 Nový

Re: NEescapovaní názvů entity (tabulky) a sloupců

celé vlákno
Jan Tichý aura:21
5. 8. 2010 8:47 Nový

Re: NEescapovaní názvů entity (tabulky) a sloupců

celé vlákno
Jan Tichý aura:21
5. 8. 2010 9:17 Nový

Re: NEescapovaní názvů entity (tabulky) a sloupců

celé vlákno

Protože Patrikem odkazovaný ticket je už closed, otevřel jsem nový – http://www.doctrine-project.org/jira/browse/DBAL-40. Takže koho tohle špatné escapování v Doctrine 2 také trápí, můžete se přidat i se svým hlasem.

srigi . aura:47
5. 8. 2010 17:41 Nový

sklamanie

celé vlákno

Po precitani clanku musim napisat, ze som z Doctrine 2 sklamany. V snippetoch vidim nenormalne velku zavislost medzi Entitou a (sry za anglictinu) underlaying storage engine. A z tejto debaty medzi autorom clanku a developerom Doctrine 2 som sklamany este viac.
Dufal som, ze Doctrine 2 sa priblizi k 5-lay Modelu, ktory uz pan Tichy popisal v dnes uz pomaly kultovom clanku u seba na blogu. Dufal som, ze Doctrine 2 mi umozni napisat domenove modely (Entity) a iba pomocou vymeny jednej triedy kdesi v 4–5 vrstve zmenit engine z MySQL na MongoDB. Je mi jasne, ze toto naprogramovat je skoro nemozne, ale ze bude Doctrine tak daleko od tohoto sna som necakal.

Václav Novotný
5. 8. 2010 22:07 Nový

Re: sklamanie

celé vlákno

Já z té debaty vůbec zklamaný nejsem. Mně pomohla uvědomit si, že to s quotováním není vůbec tak samozřejmá a jednoduchá záležitost, jak jsem si původně myslel.

Zasílat nově přidané příspěvky e-mailem