{"id":79465,"date":"2020-04-27T07:42:20","date_gmt":"2020-04-27T05:42:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh"},"modified":"2020-04-27T07:42:20","modified_gmt":"2020-04-27T05:42:20","slug":"istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","title":{"rendered":"Pravda je na prvom mjestu, ili za\u0161to se sustav treba projektirati s obzirom na strukturu baze podataka","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ahoj, Habr!<\/p>\n<p>Na\u010falej sk\u00famame t\u00e9mu <noindex><a rel=\"nofollow\" href=\"https:\/\/www.piter.com\/collection\/all\/product\/sovremennyy-yazyk-java-lyambda-vyrazheniya-potoki-i-funktsionalnoe-programmirovanie\">Java<\/a><\/noindex> a <noindex><a rel=\"nofollow\" href=\"https:\/\/storage.piter.com\/upload\/contents\/978544611587\/978544611587_X.pdf\">Spring<\/a><\/noindex>, vr\u00e1tane \u00farovne datab\u00e1z. Dnes v\u00e1m pon\u00fakame pre\u010d\u00edta\u0165 si, pre\u010do by pri navrhovan\u00ed ve\u013ek\u00fdch aplik\u00e1ci\u00ed mala ma\u0165 pr\u00e1ve \u0161trukt\u00fara datab\u00e1zy, a nie Java k\u00f3d, rozhoduj\u00faci v\u00fdznam, ako sa to rob\u00ed a ak\u00e9 s\u00fa v\u00fdnimky z tohto pravidla.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <br \/>\nV tomto dos\u0165 oneskorenom \u010dl\u00e1nku vysvetl\u00edm, pre\u010do si mysl\u00edm, \u017ee takmer vo v\u0161etk\u00fdch pr\u00edpadoch by sa model \u00fadajov v aplik\u00e1cii mal navrhova\u0165 \"vych\u00e1dzaj\u00fac z datab\u00e1zy\", a nie \"vych\u00e1dzaj\u00fac z mo\u017enost\u00ed Java\" (alebo in\u00e9ho klientskeho jazyka, s ktor\u00fdm pracujete). Ak si vyberiete druh\u00fd pr\u00edstup, vyd\u00e1vate sa na dlh\u00fa cestu bolesti a utrpenia, hne\u010f ako v\u00e1\u0161 projekt za\u010dne r\u00e1s\u0165.<\/p>\n<p>\u010cl\u00e1nok je nap\u00edsan\u00fd na z\u00e1klade <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/50706556\/kotlin-with-jooq-and-write-table-models-manually-without-code-generation\">jednej ot\u00e1zky<\/a><\/noindex>, polo\u017eenej na Stack Overflow.<\/p>\n<p>Zauj\u00edmav\u00e9 diskusie na reddite v sekci\u00e1ch <noindex><a rel=\"nofollow\" href=\"https:\/\/www.reddit.com\/r\/java\/comments\/8p0uj3\/truth_first_or_why_you_should_mostly_implement\/\">\/r\/java<\/a><\/noindex> a <noindex><a rel=\"nofollow\" href=\"https:\/\/www.reddit.com\/r\/programming\/comments\/8p0qle\/truth_first_or_why_you_should_mostly_implement\/\">\/r\/programming<\/a><\/noindex>.<\/p>\n<h4>Generovanie k\u00f3du<\/h4>\n<p>\nAk\u00e9 ve\u013ek\u00e9 prekvapenie pre m\u0148a bolo, \u017ee existuje tak\u00e1 mal\u00e1 vrstva pou\u017e\u00edvate\u013eov, ktor\u00ed, ke\u010f sa obozn\u00e1mili s jOOQ, sa rozhor\u010duj\u00fa nad t\u00fdm, \u017ee pri pr\u00e1ci s jOOQ sa na generovanie zdrojov\u00e9ho k\u00f3du spolieha v\u00e1\u017ene. Nikto v\u00e1m nebr\u00e1ni pou\u017e\u00edva\u0165 jOOQ tak, ako si mysl\u00edte, a nen\u00fati v\u00e1s pou\u017e\u00edva\u0165 generovanie k\u00f3du. Ale predvolene (tak, ako je to pop\u00edsan\u00e9 v pr\u00edru\u010dke) sa pr\u00e1ca s jOOQ uskuto\u010d\u0148uje takto: za\u010d\u00ednate so (zdedenou) sch\u00e9mou datab\u00e1zy, vykon\u00e1te jej sp\u00e4tn\u00e9 in\u017einierstvo pomocou gener\u00e1tora k\u00f3du jOOQ, aby ste z\u00edskali sadu tried reprezentuj\u00facich va\u0161e tabu\u013eky, a potom p\u00ed\u0161ete typovo bezpe\u010dn\u00e9 dotazy na tieto tabu\u013eky:<\/p>\n<pre><code class=\"java\">\tfor (Record2 record : DSL.using(configuration)\n\/\/   ^^^^^^^^^^^^^^^^^^^^^^^ Inform\u00e1cie o typoch s\u00fa odvoden\u00e9 na \n\/\/   z\u00e1klade vygenerovan\u00e9ho k\u00f3du, na ktor\u00fd sa odvol\u00e1va uveden\u00e9\n\/\/   ni\u017e\u0161ie podmienka SELECT \n \n       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)\n\/\/           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ vygenerovan\u00e9 men\u00e1\n       .from(ACTOR)\n       .orderBy(1, 2)) {\n    \/\/ ...\n}<\/code><\/pre>\n<p>\nK\u00f3d sa generuje bu\u010f ru\u010dne mimo zostavy, alebo ru\u010dne pri ka\u017edej zostave. Napr\u00edklad tak\u00e1 regener\u00e1cia m\u00f4\u017ee nasledova\u0165 hne\u010f po <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">migr\u00e1cii datab\u00e1zy Flyway, ktor\u00fa je mo\u017en\u00e9 vykona\u0165 tie\u017e ru\u010dne alebo automaticky<\/a><\/noindex>.<\/p>\n<h4>Generovanie zdrojov\u00e9ho k\u00f3du<\/h4>\n<p>\nS tak\u00fdmi pr\u00edstupmi k generovaniu k\u00f3du \u2013 ru\u010dn\u00fdmi a automatick\u00fdmi \u2013 s\u00fa spojen\u00e9 r\u00f4zne filozofie, v\u00fdhody a nev\u00fdhody, ktor\u00e9 nepl\u00e1nujem podrobne rozobera\u0165 v tomto \u010dl\u00e1nku. Ale vo v\u0161eobecnosti cel\u00e1 podstata generovan\u00e9ho k\u00f3du spo\u010d\u00edva v tom, \u017ee umo\u017e\u0148uje reprodukova\u0165 na Jave t\u00fa \u201epravdu\u201c, ktor\u00fa pova\u017eujeme za dan\u00fa, \u010di u\u017e v r\u00e1mci n\u00e1\u0161ho syst\u00e9mu, alebo mimo neho. V istom zmysle to ist\u00e9 robia kompil\u00e1tory, ktor\u00e9 generuj\u00fa bajtk\u00f3d, strojov\u00fd k\u00f3d alebo ak\u00fdsi in\u00fd typ k\u00f3du na z\u00e1klade zdrojov\u00fdch k\u00f3dov \u2013 z\u00edskavame predstavu na\u0161ej \u201epravdy\u201c v inom jazyku, bez oh\u013eadu na konkr\u00e9tne d\u00f4vody. <\/p>\n<p>Existuje mno\u017estvo tak\u00fdchto gener\u00e1torov k\u00f3du. Napr\u00edklad, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/tools\/unix\/xjc.html\">XJC m\u00f4\u017ee generova\u0165 k\u00f3d Java na z\u00e1klade s\u00faborov XSD alebo WSDL.<\/a><\/noindex>Princ\u00edp je v\u017edy rovnak\u00fd:<\/p>\n<ul>\n<li>Existuje ak\u00e1si pravda (vn\u00fatorn\u00e1 alebo vonkaj\u0161ia) \u2013 napr\u00edklad \u0161pecifik\u00e1cia, model d\u00e1t at\u010f.<\/li>\n<li>Potrebujeme lok\u00e1lne zobrazenie tejto pravdy v na\u0161om programovacom jazyku.<\/li>\n<\/ul>\n<p>\nA generova\u0165 tak\u00e9 zobrazenie je takmer v\u017edy rozumn\u00e9 \u2013 aby sa predi\u0161lo nadbyto\u010dnosti.<\/p>\n<h4>Poskytovatelia typov a spracovanie anot\u00e1ci\u00ed<\/h4>\n<p>\nNa pozn\u00e1mku: \u010fal\u0161\u00ed, modernej\u0161\u00ed a \u0161pecifickej\u0161\u00ed pr\u00edstup k generovaniu k\u00f3du pre jOOQ je spojen\u00fd s pou\u017eit\u00edm poskytovate\u013eov typov, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fsharp\/tutorials\/type-providers\/\">tak, ako s\u00fa implementovan\u00e9 v F#.<\/a><\/noindex>V takom pr\u00edpade k\u00f3d generuje kompil\u00e1tor vlastne na etapa kompil\u00e1cie. V podobe zdrojov\u00fdch k\u00f3dov tak\u00fd k\u00f3d v z\u00e1sade neexistuje. V Jave existuj\u00fa podobn\u00e9, hoci nie tak elegantn\u00e9 n\u00e1stroje \u2013 s\u00fa to procesory anot\u00e1ci\u00ed, napr\u00edklad <noindex><a rel=\"nofollow\" href=\"https:\/\/projectlombok.org\">Lombok.<\/a><\/noindex>.<\/p>\n<p>V istom zmysle sa tu dej\u00fa tie ist\u00e9 veci ako v prvom pr\u00edpade, s v\u00fdnimkou:<\/p>\n<ul>\n<li>Nevid\u00edte generovan\u00fd k\u00f3d (mo\u017eno sa niekomu t\u00e1to situ\u00e1cia nezd\u00e1 tak odstra\u0161uj\u00faca?)<\/li>\n<li>Mus\u00edte zabezpe\u010di\u0165, \u017ee typy m\u00f4\u017eu by\u0165 poskytovan\u00e9, teda \u201epravda\u201c mus\u00ed by\u0165 v\u017edy dostupn\u00e1. To je jednoduch\u00e9 v pr\u00edpade Lombok, ktor\u00fd anotuje \u201epravdu\u201c. O nie\u010do zlo\u017eitej\u0161ie je to s datab\u00e1zov\u00fdmi modelmi, ktor\u00fdch funkcia z\u00e1vis\u00ed od neust\u00e1le dostupn\u00e9ho \u017eiv\u00e9ho spojenia.<\/li>\n<\/ul>\n<p><\/p>\n<h4>Ak\u00fd je probl\u00e9m s generovan\u00edm k\u00f3du?<\/h4>\n<p>\nOkrem zlo\u017eit\u00fdch ot\u00e1zok o tom, ak\u00fdm sp\u00f4sobom je lep\u0161ie spusti\u0165 gener\u00e1ciu k\u00f3du \u2013 ru\u010dne alebo automaticky, treba spomen\u00fa\u0165 aj to, \u017ee s\u00fa \u013eudia, ktor\u00ed si myslia, \u017ee gener\u00e1cia k\u00f3du v\u00f4bec nie je potrebn\u00e1. Od\u00f4vodnenie tejto perspekt\u00edvy, s ktorou som sa naj\u010dastej\u0161ie stretol, spo\u010d\u00edva v tom, \u017ee je potom \u0165a\u017ek\u00e9 nastavi\u0165 zostavovac\u00ed pipeline. \u00c1no, naozaj to je zlo\u017eit\u00e9. Vznikaj\u00fa dodato\u010dn\u00e9 infra\u0161trukt\u00farne n\u00e1klady. Ak len za\u010d\u00ednate pracova\u0165 s ur\u010dit\u00fdm produktom (\u010di u\u017e je to jOOQ, alebo JAXB, alebo Hibernate, at\u010f.), do nastavenia pracovn\u00e9ho prostredia sa investuje \u010das, ktor\u00fd by ste radi venovali \u0161t\u00fadiu samotn\u00e9ho API, aby ste nesk\u00f4r z neho mohli vy\u0165a\u017ei\u0165 hodnotu.<\/p>\n<p>Ak s\u00fa n\u00e1klady spojen\u00e9 s porozumen\u00edm fungovaniu gener\u00e1tora pr\u00edli\u0161 vysok\u00e9 \u2013 potom naozaj API zle pracovalo na pou\u017e\u00edvate\u013eskej pr\u00edvetivosti gener\u00e1tora k\u00f3du (a nesk\u00f4r sa uk\u00e1\u017ee, \u017ee aj pou\u017e\u00edvate\u013esk\u00e9 nastavenie v \u0148om je zlo\u017eit\u00e9). Pohodlie pou\u017e\u00edvania by malo by\u0165 najvy\u0161\u0161ou prioritou pre ak\u00e9ko\u013evek tak\u00e9 API. Ale to je len jeden argument proti gener\u00e1cii k\u00f3du. V ostatnom pr\u00edpade je absol\u00fatne potrebn\u00e9 p\u00edsa\u0165 lok\u00e1lne zast\u00fapenie vn\u00fatornej alebo vonkaj\u0161ej pravdy \u00faplne ru\u010dne.<\/p>\n<p>Mnoh\u00ed povedia, \u017ee nemaj\u00fa \u010das sa t\u00fdm v\u0161etk\u00fdm zaobera\u0165. Maj\u00fa term\u00edny na dodanie svojho Super- produktu. Niekedy nesk\u00f4r vylep\u0161\u00edme zostavovacie pipeline, ur\u010dite sa stihne. Odpoviem im:<\/p>\n<p><img decoding=\"async\" alt=\"Pravda je na prvom mjestu, ili za\u0161to se sustav treba projektirati s obzirom na strukturu baze podataka\" src=\"\/wp-content\/uploads\/2020\/04\/cd9aca1e0365fa5af28cfc72c201cb8c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/www.flickr.com\/photos\/toddle_email_newsletters\/15596940251\/in\/photostream\/\">Origin\u00e1l<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"http:\/\/audiencestack.com\/static\/blog.html\">Alan O'Rourke, Audience Stack<\/a><\/noindex> <\/p>\n<p><b>Ale v Hibernate \/ JPA je tak jednoduch\u00e9 p\u00edsa\u0165 k\u00f3d \u201epre Java\u201c. <\/b><\/p>\n<p>Naozaj. Pre Hibernate a jeho pou\u017e\u00edvate\u013eov je to s\u00fa\u010dasne po\u017eehnanie a prekliatie. V Hibernate m\u00f4\u017eete jednoducho nap\u00edsa\u0165 nieko\u013eko ent\u00edt, takto:<\/p>\n<pre><code class=\"java\">\t@Entity\nclass Book {\n  @Id\n  int id;\n  String title;\n}<\/code><\/pre>\n<p>\nA takmer v\u0161etko je hotov\u00e9. Teraz je \u00falohou Hibernate generova\u0165 zlo\u017eit\u00e9 \u201edetaily\u201c toho, ako sa t\u00e1to entita presne ur\u010d\u00ed v DDL v\u00e1\u0161ho \u201edialektu\u201c SQL:<\/p>\n<pre><code class=\"sql\">\tCREATE TABLE book (\n  id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,\n  title VARCHAR(50),\n \n  CONSTRAINT pk_book PRIMARY KEY (id)\n);\n \nCREATE INDEX i_book_title ON book (title);<\/code><\/pre>\n<p>\n\u2026 a za\u010d\u00edname sp\u00fa\u0161\u0165a\u0165 aplik\u00e1ciu. Naozaj skvel\u00e1 mo\u017enos\u0165, ako sa r\u00fdchlo dosta\u0165 do pr\u00e1ce a sk\u00fa\u0161a\u0165 r\u00f4zne veci.<\/p>\n<p>Ale, dovo\u013ete. Klamal som.<\/p>\n<ul>\n<li>A \u010di Hibernate naozaj pou\u017eije defin\u00edciu tohto pomenovan\u00e9ho prim\u00e1rneho k\u013e\u00fa\u010da?<\/li>\n<li>A \u010di Hibernate vytvor\u00ed index v TITLE? \u2013 viem ur\u010dite, \u017ee ho budeme potrebova\u0165. <\/li>\n<li>A Hibernate naozaj urob\u00ed tento k\u013e\u00fa\u010d identifikuj\u00faci v Identity Specification?<\/li>\n<\/ul>\n<p>\nPravdepodobne nie. Ak vyv\u00edjate svoj projekt od za\u010diatku, je v\u017edy pohodln\u00e9 jednoducho sa zbavi\u0165 starej datab\u00e1zy a vygenerova\u0165 nov\u00fa, hne\u010f ako prid\u00e1te potrebn\u00e9 anot\u00e1cie. Takto entita Book nakoniec z\u00edska tvar: <\/p>\n<pre><code class=\"java\">\t@Entity\n@Table(name = \"book\", indexes = {\n  @Index(name = \"i_book_title\", columnList = \"title\").\n})\nclass Book {\n  @Id\n  @GeneratedValue(strategy = IDENTITY)\n  int id;\n  String title;\n}\n<\/code><\/pre>\n<p>\nSuper. Vygenerova\u0165 znova. Op\u00e4\u0165, v takom pr\u00edpade bude na za\u010diatku ve\u013emi jednoduch\u00e9.<\/p>\n<h4>Ale nesk\u00f4r za to budete musie\u0165 zaplati\u0165.<\/h4>\n<p>\nSk\u00f4r \u010di nesk\u00f4r sa budete musie\u0165 presun\u00fa\u0165 do produkcie. A pr\u00e1ve vtedy tak\u00fd model prestane fungova\u0165. Preto\u017ee: <\/p>\n<p>V produkcii u\u017e nebude mo\u017en\u00e9 v pr\u00edpade potreby zlikvidova\u0165 star\u00fa datab\u00e1zu a za\u010da\u0165 v\u0161etko odznova. Va\u0161a datab\u00e1za sa stane dedi\u010dnou.<\/p>\n<p>Od teraz a nav\u017edy budete musie\u0165 p\u00edsa\u0165 <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">migra\u010dn\u00e9 skripty DDL, napr\u00edklad pomocou Flyway.<\/a><\/noindex>. A \u010do sa v takom pr\u00edpade stane s va\u0161imi entitami? Budete ich m\u00f4c\u0165 bu\u010f prisp\u00f4sobi\u0165 ru\u010dne (a tak zdvojn\u00e1sob\u00edte mno\u017estvo pr\u00e1ce), alebo prik\u00e1\u017eete Hibernate, aby ich znova vygeneroval pre v\u00e1s (ak\u00e1 ve\u013ek\u00e1 je \u0161anca, \u017ee takto vygenerovan\u00fd bude zodpoveda\u0165 va\u0161im o\u010dak\u00e1vaniam?) Tak \u010di onak, prehr\u00e1vate.<\/p>\n<p>Takto, ke\u010f sa presuniete do produkcie, budete potrebova\u0165 hor\u00face opravy. A tie mus\u00edte r\u00fdchlo implementova\u0165 do produkcie. Ke\u010f\u017ee ste sa na to nepripravili a neorganizovali ste plynul\u00fd prenos va\u0161ich migr\u00e1ci\u00ed do produkcie, v\u0161etko to drasticky oprav\u00edte. A potom u\u017e nestihnete v\u0161etko spravi\u0165 spr\u00e1vne. A obvi\u0148ujete Hibernate, preto\u017ee v\u017edy je niekto in\u00fd vinn\u00fd, len nie vy...<\/p>\n<p>Namiesto toho sa to od za\u010diatku dalo robi\u0165 \u00faplne inak. Napr\u00edklad da\u0165 na bicykel okr\u00fahle koles\u00e1.<\/p>\n<h4>Najprv datab\u00e1za.<\/h4>\n<p>\nSkuto\u010dn\u00e1 \"pravda\" v sch\u00e9me va\u0161ej datab\u00e1zy a \"suverenita\" nad \u0148ou spo\u010d\u00edva v datab\u00e1ze. Sch\u00e9ma je definovan\u00e1 iba v samotnej datab\u00e1ze a nikde inde, a ka\u017ed\u00fd z klientov m\u00e1 k\u00f3piu tejto sch\u00e9my, tak\u017ee je \u00faplne rozumn\u00e9 vynucova\u0165 dodr\u017eiavanie sch\u00e9my a jej integrity priamo v datab\u00e1ze \u2013 tam, kde s\u00fa ulo\u017een\u00e9 inform\u00e1cie. <br \/>\nTo je star\u00e1, dokonca aj opotrebovan\u00e1 m\u00fadros\u0165. Prim\u00e1rne a unik\u00e1tne k\u013e\u00fa\u010de s\u00fa dobr\u00e9. Cudzie k\u013e\u00fa\u010de \u2013 dobr\u00e9. Kontrola obmedzen\u00ed \u2013 dobr\u00e9. <noindex><a rel=\"nofollow\" href=\"https:\/\/community.oracle.com\/ideas\/13028\">Tvrdenia<\/a><\/noindex> \u2013 dobr\u00e9. <\/p>\n<p>A to v\u0161ak nie je v\u0161etko. Napr\u00edklad pri pou\u017eit\u00ed Oracle pravdepodobne budete chcie\u0165 uvies\u0165:<\/p>\n<ul>\n<li>V ktorom tabu\u013ekovom priestore sa nach\u00e1dza va\u0161a tabu\u013eka <\/li>\n<li>Ak\u00e1 je jej hodnota PCTFREE <\/li>\n<li>Ak\u00e1 je ve\u013ekos\u0165 cache vo va\u0161ej sekvencii (za identifik\u00e1torom)<\/li>\n<\/ul>\n<p>\nMo\u017eno, \u017ee to v\u0161etko nie je d\u00f4le\u017eit\u00e9 v mal\u00fdch syst\u00e9moch, ale nemus\u00edte \u010daka\u0165 na prechod do oblasti \u201eve\u013ek\u00fdch d\u00e1t\u201c \u2014 m\u00f4\u017eete za\u010da\u0165 \u010derpa\u0165 v\u00fdhody zo zdrojov optimaliz\u00e1cie u poskytovate\u013ea sk\u00f4r, ako sa dostanete do v\u00e4\u010d\u0161\u00edch syst\u00e9mov, ako s\u00fa spom\u00ednan\u00e9 vy\u0161\u0161ie. \u017diadna z ORM, ktor\u00fa som videl (vr\u00e1tane jOOQ), neposkytuje pr\u00edstup k \u00faplnej sade mo\u017enost\u00ed DDL, ktor\u00e9 mo\u017eno budete chcie\u0165 pou\u017ei\u0165 vo svojej datab\u00e1ze. ORM pon\u00fakaj\u00fa niektor\u00e9 n\u00e1stroje, ktor\u00e9 pom\u00e1haj\u00fa pri p\u00edsan\u00ed DDL.<\/p>\n<p>Ale nakoniec dobre navrhnut\u00e1 sch\u00e9ma je nap\u00edsan\u00e1 ru\u010dne v DDL. Ak\u00fdko\u013evek generovan\u00fd DDL je len jej aproxim\u00e1ciou.<\/p>\n<h4>\u010co na to klientsk\u00fd model?<\/h4>\n<p>\nAko bolo spomenut\u00e9 vy\u0161\u0161ie, na klientovi budete potrebova\u0165 k\u00f3piu sch\u00e9my va\u0161ej datab\u00e1zy, klientsk\u00e9 zobrazenie. Zbyto\u010dne uv\u00e1dza\u0165, \u017ee toto klientsk\u00e9 zobrazenie mus\u00ed by\u0165 synchronizovan\u00e9 s re\u00e1lnym modelom. Ako toho najlep\u0161ie dosiahnu\u0165? Pomocou gener\u00e1tora k\u00f3du.<\/p>\n<p>V\u0161etky datab\u00e1zy poskytuj\u00fa svoje meta inform\u00e1cie cez SQL. Takto m\u00f4\u017eete z\u00edska\u0165 zo svojej datab\u00e1zy v\u0161etky tabu\u013eky v r\u00f4znych dialektoch SQL:<\/p>\n<pre><code class=\"sql\">\t-- H2, HSQLDB, MySQL, PostgreSQL, SQL Server\nSELECT table_schema, table_name\nFROM information_schema.tables\n\n-- DB2\nSELECT tabschema, tabname\nFROM syscat.tables\n\n-- Oracle\nSELECT owner, table_name\nFROM all_tables\n\n-- SQLite\nSELECT name\nFROM sqlite_master\n\n-- Teradata\nSELECT databasename, tablename\nFROM dbc.tables\n<\/code><\/pre>\n<p>\nTieto dotazy (alebo podobn\u00e9, v z\u00e1vislosti od toho, \u010di sa musia bra\u0165 do \u00favahy aj poh\u013eady, materializovan\u00e9 poh\u013eady, funkcie s tabli\u010dn\u00fdm hodnoten\u00edm) sa tie\u017e vykon\u00e1vaj\u00fa prostredn\u00edctvom volania <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/javase\/10\/docs\/api\/java\/sql\/DatabaseMetaData.html#getTables(java.lang.String,java.lang.String,java.lang.String,java.lang.String%5B%5D)\"><code>DatabaseMetaData.getTables()<\/code><\/a><\/noindex> z JDBC, alebo pomocou meta-modulu jOOQ.<\/p>\n<p>Z v\u00fdsledkov tak\u00fdchto dotazov je relat\u00edvne \u013eahk\u00e9 vygenerova\u0165 ak\u00e9ko\u013evek klientsk\u00e9 zobrazenie modelu va\u0161ej datab\u00e1zy, bez oh\u013eadu na to, ak\u00e1 technol\u00f3gia sa pou\u017e\u00edvaj\u00fa na va\u0161ej strane.<\/p>\n<ul>\n<li>Ak pou\u017e\u00edvate JDBC alebo Spring, m\u00f4\u017eete vytvori\u0165 mno\u017einu textov\u00fdch kon\u0161t\u00e1nt <\/li>\n<li>Ak pou\u017e\u00edvate JPA, m\u00f4\u017eete vygenerova\u0165 samotn\u00e9 entity <\/li>\n<li>Ak pou\u017e\u00edvate jOOQ, m\u00f4\u017eete vygenerova\u0165 meta-model jOOQ<\/li>\n<\/ul>\n<p>\nV z\u00e1vislosti od toho, ak\u00fd objem mo\u017enost\u00ed pon\u00faka v\u00e1\u0161 klientsky API (napr. jOOQ alebo JPA), m\u00f4\u017ee by\u0165 vygenerovan\u00fd meta-model skuto\u010dne bohat\u00fd a kompletn\u00fd. Zoberme si napr\u00edklad mo\u017enos\u0165 implicitn\u00fdch spojen\u00ed, <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2018\/02\/20\/type-safe-implicit-join-through-path-navigation-in-jooq-3-11\/\">ktor\u00e1 sa objavila v jOOQ 3.11<\/a><\/noindex>, ktor\u00e1 sa zaklad\u00e1 na vygenerovan\u00fdch metainform\u00e1ci\u00e1ch o vz\u0165ahoch medzi va\u0161imi tabu\u013ekami na z\u00e1klade cudz\u00edch k\u013e\u00fa\u010dov.<\/p>\n<p>Teraz ka\u017ed\u00e9 zv\u00fd\u0161enie datab\u00e1zy automaticky sp\u00f4sob\u00ed aktualiz\u00e1ciu klientsk\u00e9ho k\u00f3du. Predstavte si napr\u00edklad:<\/p>\n<pre><code class=\"sql\">ALTER TABLE book RENAME COLUMN title TO book_title;<\/code><\/pre>\n<p>\nNaozaj by ste chceli robi\u0165 t\u00fato pr\u00e1cu dvakr\u00e1t? Ur\u010dite nie. Jednoducho ulo\u017e\u00edme DDL, pre\u017eeneme ho cez v\u00e1\u0161 build pipeline a z\u00edskame aktualizovan\u00fa entitu:<\/p>\n<pre><code class=\"java\">@Entity\n@Table(name = \"book\", indexes = {\n \n  \/\/ Prem\u00fd\u0161\u013eali ste nad t\u00fdm?\n  @Index(name = \"i_book_title\", columnList = \"book_title\").\n})\nclass Book {\n  @Id\n  @GeneratedValue(strategy = IDENTITY)\n  int id;\n \n  @Column(\"book_title\")\n  String bookTitle;\n}<\/code><\/pre>\n<p>\nAlebo aktualizovan\u00fa triedu jOOQ. V\u00e4\u010d\u0161ina zmien DDL sa odr\u00e1\u017ea aj na semantike, nielen na syntaktike. Preto m\u00f4\u017ee by\u0165 u\u017eito\u010dn\u00e9 pozrie\u0165 sa na skompilovan\u00fd k\u00f3d, ktor\u00fd k\u00f3d bude (alebo m\u00f4\u017ee by\u0165) ovplyvnen\u00fd zv\u00fd\u0161en\u00edm va\u0161ej datab\u00e1zy.<\/p>\n<h4>Jedna pravda<\/h4>\n<p>\nBez oh\u013eadu na to, ak\u00fa technol\u00f3giu pou\u017e\u00edvate, v\u017edy existuje jeden model, ktor\u00fd je jedin\u00fdm zdrojom pravdy pre ur\u010dit\u00fd subsyst\u00e9m \u2013 alebo, minim\u00e1lne, mali by sme sa o to sna\u017ei\u0165 a vyhn\u00fa\u0165 sa takej podnikovej zm\u00e4tku, kde je \"pravda\" okam\u017eite v\u0161ade a nikde. V\u0161etko m\u00f4\u017ee by\u0165 ove\u013ea jednoduch\u0161ie. Ak iba vymie\u0148ate XML s\u00fabory s nejak\u00fdm in\u00fdm syst\u00e9mom, jednoducho pou\u017e\u00edvajte XSD. Pozrite sa na metamodel INFORMATION_SCHEMA z jOOQ vo form\u00e1te XML:<br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/www.jooq.org\/xsd\/jooq-meta-3.10.0.xsd\">https:\/\/www.jooq.org\/xsd\/jooq-meta-3.10.0.xsd<\/a><\/noindex><\/p>\n<ul>\n<li>XSD je dobre pochopite\u013en\u00e9<\/li>\n<li>XSD ve\u013emi dobre ozna\u010duje obsah XML a umo\u017e\u0148uje valid\u00e1ciu vo v\u0161etk\u00fdch klientskych jazykoch <\/li>\n<li>XSD je dobre verzionovate\u013en\u00e9 a m\u00e1 rozsiahlu sp\u00e4tn\u00fa kompatibilitu <\/li>\n<li>XSD m\u00f4\u017ee by\u0165 prelo\u017een\u00e9 do k\u00f3du Java pomocou XJC<\/li>\n<\/ul>\n<p>\nPosledn\u00fd bod je d\u00f4le\u017eit\u00fd. Pri komunik\u00e1cii s extern\u00fdm syst\u00e9mom pomocou XML spr\u00e1v chceme ma\u0165 istotu o platnosti na\u0161ich spr\u00e1v. Toho je ve\u013emi \u013eahk\u00e9 dosiahnu\u0165 pomocou JAXB, XJC a XSD. Bolo by to \u00fapln\u00e9 \u0161ialenstvo o\u010dak\u00e1va\u0165, \u017ee pri pr\u00edstupe k n\u00e1vrhu \u201enajprv Java\u201c, kde vytv\u00e1rame na\u0161e spr\u00e1vy vo forme objektov Java, by sa dali nejako zrozumite\u013ene zobrazi\u0165 na XML a zasla\u0165 na spracovanie do in\u00e9ho syst\u00e9mu. XML generovan\u00e9 tak\u00fdmto sp\u00f4sobom by malo ve\u013emi n\u00edzku kvalitu, nebolo by zdokumentovan\u00e9 a \u0165a\u017eko by sa vyv\u00edjalo. Ak by existovala dohoda o \u00farovni kvality slu\u017eieb (SLA) pre tak\u00fdto rozhranie, okam\u017eite by sme ju skazili.<\/p>\n<p>\u00daprimne povedan\u00e9, presne toto sa neust\u00e1le deje s API na JSON, ale to je u\u017e in\u00fd pr\u00edbeh, nabud\u00face sa o tom roz\u010d\u00falim\u2026 <\/p>\n<h4>Datab\u00e1zy: je to to ist\u00e9<\/h4>\n<p>\nPri pr\u00e1ci s datab\u00e1zami si uvedomujete, \u017ee v\u0161etky s\u00fa v z\u00e1sade podobn\u00e9. Datab\u00e1za vlastn\u00ed svoje d\u00e1ta a mala by riadi\u0165 sch\u00e9mu. Ak\u00e9ko\u013evek modifik\u00e1cie v sch\u00e9me by mali by\u0165 implementovan\u00e9 priamo na DDL, aby sa aktualizoval jednotn\u00fd zdroj pravdy.<\/p>\n<p>Ke\u010f sa aktualiz\u00e1cia zdroja uskuto\u010dn\u00ed, v\u0161etci klienti by mali tie\u017e aktualizova\u0165 svoje k\u00f3pie modelu. Niektor\u00ed klienti m\u00f4\u017eu by\u0165 nap\u00edsan\u00ed v Jave pomocou jOOQ a Hibernate alebo JDBC (alebo v\u0161etky naraz). In\u00ed klienti m\u00f4\u017eu by\u0165 nap\u00edsan\u00ed v Perle (ost\u00e1va im popria\u0165 \u0161\u0165astie), traja \u2013 na C#. To nie je d\u00f4le\u017eit\u00e9. Hlavn\u00fd model je v datab\u00e1ze. Modely generovan\u00e9 pomocou ORM s\u00fa zvy\u010dajne n\u00edzkej kvality, zle zdokumentovan\u00e9 a \u0165a\u017eko sa vyv\u00edjaj\u00fa.<\/p>\n<p>Preto nerobte chyby. Od za\u010diatku sa vyhnite chyb\u00e1m. Pracujte na z\u00e1klade datab\u00e1zy. Vytvorte tak\u00fd nasadzovac\u00ed proces, ktor\u00fd je mo\u017en\u00e9 automatizova\u0165. Zahr\u0148te gener\u00e1tory k\u00f3du, aby ste pohodlne skop\u00edrovali model va\u0161ej datab\u00e1zy a odovzdali ho na klientov. A presta\u0148te sa ob\u00e1va\u0165 gener\u00e1torov k\u00f3du. S\u00fa dobr\u00e9. S nimi sa stanete produkt\u00edvnej\u0161\u00edmi. Je potrebn\u00e9 len na za\u010diatku venova\u0165 trochu \u010dasu ich nastaveniu \u2013 a potom v\u00e1s \u010dakaj\u00fa roky zv\u00fd\u0161enej produktivity, ktor\u00e9 sa v kone\u010dnom d\u00f4sledku stan\u00fa hist\u00f3riou v\u00e1\u0161ho projektu.<\/p>\n<p>Zatia\u013e ne\u010fakujte, nesk\u00f4r.<\/p>\n<h4>Vysvetlenie<\/h4>\n<p>\nPre jasnos\u0165: Tento \u010dl\u00e1nok ur\u010dite nepropaguje, \u017ee cel\u00e1 va\u0161a syst\u00e9m mus\u00ed by\u0165 prisp\u00f4soben\u00e1 modelu va\u0161ej datab\u00e1zy (t.j. predmetn\u00e1 oblas\u0165, obchodn\u00e1 logika at\u010f.). V tomto \u010dl\u00e1nku hovor\u00edm o tom, \u017ee klientsky k\u00f3d, ktor\u00fd interaguje s datab\u00e1zou, by sa mal orientova\u0165 na model datab\u00e1zy, aby v jeho vlastnom obsahu nebola reprodukovan\u00e1 datab\u00e1zov\u00e1 sch\u00e9ma v statusu \u201eprvej triedy\u201c. Tak\u00e1to logika je zvy\u010dajne umiestnen\u00e1 na \u00farovni pr\u00edstupu k d\u00e1tam u v\u00e1s na kliente.<\/p>\n<p>V dvoj\u00farov\u0148ov\u00fdch architekt\u00farach, ktor\u00e9 sa e\u0161te st\u00e1le niekde zachovali, m\u00f4\u017ee by\u0165 tak\u00fdto model syst\u00e9mu jedinou mo\u017enos\u0165ou. Av\u0161ak vo v\u00e4\u010d\u0161ine syst\u00e9mov sa \u00farove\u0148 pr\u00edstupu k d\u00e1tam jav\u00ed ako \u201epod syst\u00e9m\u201c, ktor\u00fd enkapsuluje model datab\u00e1zy.<\/p>\n<h4>V\u00fdnimky<\/h4>\n<p>\nZ ak\u00e9hoko\u013evek pravidla existuj\u00fa v\u00fdnimky, a u\u017e som povedal, \u017ee pr\u00edstup s prioritou datab\u00e1zy a generovanie zdrojov\u00e9ho k\u00f3du sa niekedy m\u00f4\u017ee uk\u00e1za\u0165 ako nevhodn\u00fd. Tu je p\u00e1r tak\u00fdchto v\u00fdnimiek (pravdepodobne existuj\u00fa aj in\u00e9):<\/p>\n<ul>\n<li>Ke\u010f nie je zn\u00e1ma sch\u00e9ma a je potrebn\u00e9 ju otvori\u0165. Napr\u00edklad, ste poskytovate\u013e n\u00e1stroja, ktor\u00fd pom\u00e1ha pou\u017e\u00edvate\u013eom orientova\u0165 sa v akejko\u013evek sch\u00e9me. Uf. Bez generovania k\u00f3du tu. Ale aj tak \u2013 datab\u00e1za je predov\u0161etk\u00fdm.<\/li>\n<li>Ke\u010f by sa sch\u00e9ma mala generova\u0165 na po\u017eiadanie na rie\u0161enie nejak\u00e9ho probl\u00e9mu. Tento pr\u00edklad sa jav\u00ed ako trochu komplikovan\u00e1 verzia vzoru <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">entity attribute value<\/a><\/noindex>, t.j., naozaj nem\u00e1te jasne definovan\u00fa sch\u00e9mu. V takomto pr\u00edpade \u010dasto ani nie je mo\u017en\u00e9 by\u0165 si ist\u00fd, \u017ee v\u00e1m bude vyhovova\u0165 RDBMS.<\/li>\n<\/ul>\n<p>\nV\u00fdnimky s\u00fa z podstaty v\u00fdnimo\u010dn\u00e9. Vo v\u00e4\u010d\u0161ine situ\u00e1ci\u00ed s\u00favisiacich s pou\u017eit\u00edm RDBMS je sch\u00e9ma zn\u00e1ma vopred, nach\u00e1dza sa v RDBMS a je jedin\u00fdm zdrojom \u201epravdy\u201c, a v\u0161etci klienti musia z\u00edska\u0165 k\u00f3pie odvoden\u00e9 od nej. Ide\u00e1lne by sa pritom mal pou\u017e\u00edva\u0165 gener\u00e1tor k\u00f3du.<br \/>\n<br \/>Zdroj: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/piter\/blog\/498816\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443 Java \u0438 Spring, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043f\u043e\u0447\u0435\u043c\u0443 \u043f\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u043d\u0435 \u043a\u043e\u0434 Java, \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f, \u0438 \u043a\u0430\u043a\u0438\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430. \u0412 \u044d\u0442\u043e\u0439 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u043e\u0437\u0434\u0430\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043e\u0431\u044a\u044f\u0441\u043d\u044e, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":79466,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-79465","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"sk_SK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0418\u0441\u0442\u0438\u043d\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-27T05:42:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-27T05:42:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 Pravda predov\u0161etk\u00fdm, alebo pre\u010do by sa syst\u00e9m mal navrhova\u0165 na z\u00e1klade \u0161trukt\u00fary datab\u00e1zy | ProHoster","description":"Ahoj, Habr! Pokra\u010dujeme v sk\u00faman\u00ed t\u00e9my","canonical_url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sk_SK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0418\u0441\u0442\u0438\u043d\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u0438\u043b\u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043c\u0443","og:url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-04-27T05:42:20+00:00","article:modified_time":"2020-04-27T05:42:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"79465","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:37:24","updated":"2022-09-29 16:13:15","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/79465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/comments?post=79465"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/79465\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media\/79466"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media?parent=79465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/categories?post=79465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/tags?post=79465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}