{"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\/et\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh","title":{"rendered":"T\u00f5de eelk\u00f5ige, v\u00f5i miks s\u00fcsteemi tuleb projekteerida, l\u00e4htudes andmebaasi struktuurist","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Tere, Habr!<\/p>\n<p>Me j\u00e4tkame teema uurimist <noindex><a rel=\"nofollow\" href=\"https:\/\/www.piter.com\/collection\/all\/product\/sovremennyy-yazyk-java-lyambda-vyrazheniya-potoki-i-funktsionalnoe-programmirovanie\">Java<\/a><\/noindex> ja <noindex><a rel=\"nofollow\" href=\"https:\/\/storage.piter.com\/upload\/contents\/978544611587\/978544611587_X.pdf\">Spring<\/a><\/noindex>, sealhulgas andmebaaside tasemel. T\u00e4na soovitame lugeda, miks suuremate rakenduste kavandamisel peaks andmebaasi struktuur, mitte Java-kood olema otsustav, kuidas seda tehakse ja millised erandid selle reegli osas on.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <br \/>\nSelles \u00fcsna hilinenud artiklis selgitan, miks arvan, et peaaegu k\u00f5igis juhtudel peaks rakenduse andmemudel olema kavandatud 'andmebaasist l\u00e4htuvalt', mitte 'Java v\u00f5imalustest l\u00e4htuvalt' (v\u00f5i muust kliendikeelest, millega t\u00f6\u00f6tate). Kui valite teise l\u00e4henemise, astute pika valu ja kannatuste teele, kui teie projekt hakkab kasvama.<\/p>\n<p>Artikkel on kirjutatud inspiratsiooniks <noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/50706556\/kotlin-with-jooq-and-write-table-models-manually-without-code-generation\">\u00fchele k\u00fcsimusele<\/a><\/noindex>, mille esitas Stack Overflow'is.<\/p>\n<p>Huvitavad arutelud reddit'i osades <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> ja <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>Koodi genereerimine<\/h4>\n<p>\nMa olin h\u00e4mmingus, et on nii v\u00e4ike kasutajate kiht, kes, tutvudes jOOQ'ga, kurdavad selle \u00fcle, et jOOQ puhul toetutakse t\u00f5siselt koodi genereerimisele. Keegi ei takista teil kasutada jOOQ'd nii, nagu soovite, ja ei sundi teid koodi genereerimist kasutama. Kuid vaike seadistuse (nagu on kirjeldatud juhendis) puhul t\u00f6\u00f6tab jOOQ nii: alustate (p\u00e4randatud) andmebaasi skeemist, viite l\u00e4bi selle tagasiprojekteerimise jOOQ koodi generaatori abil, et luua klasside kogum, mis esindab teie tabeleid, ja seej\u00e4rel kirjutate t\u00fc\u00fcbisoodsad p\u00e4ringud nende tabelite jaoks:<\/p>\n<pre><code class=\"java\">\tfor (Record2 record : DSL.using(configuration)\n\/\/   ^^^^^^^^^^^^^^^^^^^^^^^ T\u00fc\u00fcpide teave on tuletatud\n\/\/   genereeritud koodist, millele viidatakse allolevas\n\/\/   SELECT tingimuses\n\n       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)\n\/\/           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ genereeritud nimed\n       .from(ACTOR)\n       .orderBy(1, 2)) {\n    \/\/ ...\n}<\/code><\/pre>\n<p>\nKood genereeritakse kas k\u00e4sitsi v\u00e4ljaspool koostamist v\u00f5i k\u00e4sitsi iga koostamise ajal. N\u00e4iteks selline regeneratsioon v\u00f5ib toimuda kohe p\u00e4rast <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">Flyway andmebaasi migratsiooni, mida saab samuti teostada k\u00e4sitsi v\u00f5i automaatselt<\/a><\/noindex>.<\/p>\n<h4>Allikakoodi genereerimine<\/h4>\n<p>\nTugipool, kuidas koodi genereerimist \u2013 k\u00e4sitsi ja automaatsete meetoditega \u2013 seostatakse erinevate filosoofiate, eeliste ja puudustega, mida ma ei kavatse selles artiklis \u00fcksikasjalikult arutada. Kuid \u00fcldiselt on genereeritud koodi tuum selles, et see v\u00f5imaldab Java-s t\u00f5lgendada seda \u201et\u00f5de\u201d, mida me v\u00f5tame iseenesestm\u00f5istetavaks, kas meie s\u00fcsteemi raames v\u00f5i v\u00e4ljaspool seda. Teatud m\u00f5ttes teevad sama ka kompilaatorid, genereerides baitkoodi, masinkoodi v\u00f5i m\u00f5ne muu koodi vormi l\u00e4htedokumentide p\u00f5hjal \u2013 saame meie \u201et\u00f5e\u201d esituse teises keeles, s\u00f5ltumata konkreetsest p\u00f5hjusest. <\/p>\n<p>On palju selliseid koodigeneraatoreid. N\u00e4iteks, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/tools\/unix\/xjc.html\">XJC saab genereerida Java koodi XSD v\u00f5i WSDL failide p\u00f5hjal.<\/a><\/noindex>P\u00f5him\u00f5te on alati sama:<\/p>\n<ul>\n<li>On mingi t\u00f5de (sisemine v\u00f5i v\u00e4line) \u2013 n\u00e4iteks spetsifikatsioon, andmemudel jne.<\/li>\n<li>Me vajame kohaliku esitluse loomist selles t\u00f5des meie programmeerimiskeeles.<\/li>\n<\/ul>\n<p>\nPealegi on sellise esitluse genereerimine peaaegu alati m\u00f5istlik \u2013 et v\u00e4ltida liigset kordust.<\/p>\n<h4>T\u00fc\u00fcpide pakkujad ja annotatsioonide t\u00f6\u00f6tlemine<\/h4>\n<p>\nM\u00e4rkus: veel \u00fcks, kaasaegsem ja spetsiifilisem l\u00e4henemine koodi genereerimiseks jOOQ jaoks, on seotud t\u00fc\u00fcpide pakkujate kasutamisega, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/fsharp\/tutorials\/type-providers\/\">nagu need on rakendatud F#-is.<\/a><\/noindex>Sel juhul genereerib koodi kompilaator, tegelikult kompileerimise etapis. Sellise koodi l\u00e4htefailid ei eksisteeri p\u00f5him\u00f5tteliselt. Java-s on sarnaseid, kuigi mitte nii elegantseid t\u00f6\u00f6riistu \u2013 need on annotatsiooniprotsessorid, n\u00e4iteks, <noindex><a rel=\"nofollow\" href=\"https:\/\/projectlombok.org\">Lombok.<\/a><\/noindex>.<\/p>\n<p>Teatud m\u00f5ttes toimub siin sama, mis esimesel juhul, v\u00e4lja arvatud:<\/p>\n<ul>\n<li>Te ei n\u00e4e genereeritud koodi (v\u00f5ib-olla tundub see kellelegi v\u00e4hem hirmutav?)<\/li>\n<li>Te peate tagama, et t\u00fc\u00fcbid oleksid kergesti k\u00e4ttesaadavad, see t\u00e4hendab, et \u201et\u00f5de\u201d peab alati olema k\u00e4tte saadav. See on lihtne Lomboki puhul, mis annotatsiooniga \u201et\u00f5de\u201d t\u00e4histab. Veidi keerulisem on andmemudelitega, mille t\u00f6\u00f6 s\u00f5ltub pidevalt k\u00e4ttesaadavast elavast \u00fchendusest.<\/li>\n<\/ul>\n<p><\/p>\n<h4>Mis on probleem koodi genereerimisel?<\/h4>\n<p>\nLisaks keerulisele k\u00fcsimusele selle kohta, kuidas koodi genereerimist k\u00f5ige paremini alustada - k\u00e4sitsi v\u00f5i automaatselt, tuleb mainida ka, et on inimesi, kes arvavad, et koodi genereerimine pole \u00fcldse vajalik. Selle seisukoha p\u00f5hjenduseks tuuakse k\u00f5ige sagedamini v\u00e4lja, et siis on keeruline seadistada kogumis\u00fcsteemi. Jah, see on t\u00f5epoolest keeruline. Tekkivad lisainfrastruktuuri kulud. Kui alustate teatud tootega (olgu see jOOQ, JAXB v\u00f5i Hibernate jne), siis kulub arenduskeskkonna seadistamisele aega, mida tahaksite pigem kasutada API tutvumiseks, et hiljem sellest v\u00e4\u00e4rtust v\u00e4lja tuua.<\/p>\n<p>Kui kulu, mis on seotud generaatori \u00fclesehitusega, on liiga suur, siis t\u00f5epoolest on API-s koodi generaatori kasutatavus halvasti tehtud (ja hiljem selgub, et ka kasutaja seadistamine on keeruline). Kasutamise mugavus peaks olema iga sellise API k\u00f5rgeim prioriteet. Kuid see on vaid \u00fcks argument koodi genereerimise vastu. Muus osas on t\u00e4iesti m\u00f5istlik kirjutada kohalik esitus sisemisest v\u00f5i v\u00e4lsest t\u00f5est k\u00e4sitsi.<\/p>\n<p>Paljud \u00fctlevad, et neil pole aega sellega tegeleda. Neil on t\u00e4htajad oma Super-Toote osas. Kord hiljem tegeleme kogumis\u00fcsteemidega, j\u00f5uab k\u00fcll. Ma vastan neile:<\/p>\n<p><img decoding=\"async\" alt=\"T\u00f5de eelk\u00f5ige, v\u00f5i miks s\u00fcsteemi tuleb projekteerida, l\u00e4htudes andmebaasi struktuurist\" 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\/\">Originaal<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"http:\/\/audiencestack.com\/static\/blog.html\">Alan O'Rourke, Audience Stack<\/a><\/noindex> <\/p>\n<p><b>Kuid Hibernate \/ JPA-s on nii lihtne kirjutada koodi \"Java\" jaoks. <\/b><\/p>\n<p>T\u00f5epoolest. Hibernate'i ja selle kasutajate jaoks on see samal ajal \u00f5nn ja needus. Hibernate'i puhul saab lihtsalt kirjutada paar \u00fcksust, n\u00e4iteks nii:<\/p>\n<pre><code class=\"java\">\t@Entity\nclass Book {\n  @Id\n  int id;\n  String title;\n}<\/code><\/pre>\n<p>\nJa peaaegu k\u00f5ik on valmis. N\u00fc\u00fcd on Hibernate'i \u00fclesanne genereerida keerulised \"detailid\", kuidas see \u00fcksus t\u00e4pselt m\u00e4\u00e4ratakse teie SQL \"dialekti\" DDL-s:<\/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... ja hakkame rakendust k\u00e4ivitama. T\u00f5eliselt suurep\u00e4rane v\u00f5imalus, et kiiresti t\u00f6\u00f6le asuda ja erinevaid asju katsetada.<\/p>\n<p>Kuid lubage, et ma eksisin.<\/p>\n<ul>\n<li>Kas Hibernate t\u00f5eliselt rakendab selle nimetatud primaarv\u00f5tme m\u00e4\u00e4ratlemist?<\/li>\n<li>Kas Hibernate loob indeksi TITLE-s? - ma tean kindlalt, et me vajame seda. <\/li>\n<li>Ja kas Hibernate teeb selle v\u00f5tmest identifitseeriva Identity Specificationi?<\/li>\n<\/ul>\n<p>\nIlmselt mitte. Kui arendate oma projekti nullist, on alati mugav lihtsalt vana andmebaas k\u00f5rvaldada ja luua uus, kui olete vajalikud annotatsioonid lisanud. Nii n\u00e4eb l\u00f5puks v\u00e4lja olend Book: <\/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>\nV\u00e4ga hea. Genereeri uuesti. Taaskord, sel juhul on alguses v\u00e4ga lihtne.<\/p>\n<h4>Aga hiljem tuleb selle eest tasuda.<\/h4>\n<p>\nVarem v\u00f5i hiljem peate minema tootmisse. Just siis lakkab see mudel t\u00f6\u00f6tamast. Sest: <\/p>\n<p>Tootmises ei saa te enam vajadusel vana andmebaasi k\u00f5rvaldada ja k\u00f5ike puhtalt lehelt alustada. Teie andmebaas muutub p\u00e4randiks.<\/p>\n<p>Edaspidi peate kirjutama <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2014\/06\/25\/flyway-and-jooq-for-unbeatable-sql-development-productivity\/\">DDL migratsiooniskripte, n\u00e4iteks Flyway abil.<\/a><\/noindex>. Aga mis siis juhtub teie olenditega? Saate kas kohandada neid k\u00e4sitsi (ja suurendada oma t\u00f6\u00f6mahtu kahekordseks) v\u00f5i k\u00fcsida Hibernate'ilt, et ta genereeriks need uuesti teie jaoks (kui suured on v\u00f5imalused, et sellisel viisil genereeritud vastab teie ootustele?) Igatahes j\u00e4\u00e4te kaotajaks.<\/p>\n<p>Nii et niipea, kui l\u00e4hete tootmisse, vajate kiireid pat\u0161e. Ja neid tuleb tootmisse viia v\u00e4ga kiiresti. Kuna te pole valmistunud ega organiseerinud sujuvat tootmisprotsessi oma migratsioonide jaoks, peate k\u00f5ik tormiliselt pat\u0161eerima. Ja siis ei j\u00f5ua te k\u00f5ike \u00f5igesti teha. Ja s\u00fc\u00fcdistate Hibernate'i, kuna alati on s\u00fc\u00fcdi keegi muu, mitte teie...<\/p>\n<p>Selle asemel oleks algusest peale saanud teha k\u00f5ik hoopis teisiti. N\u00e4iteks panna jalgrattale \u00fcmmargused rattad.<\/p>\n<h4>Esialgu andmebaas.<\/h4>\n<p>\nT\u00f5eline \u201et\u00f5de\u201d teie andmebaasi skeemis ja \u201esuver\u00e4\u00e4nsus\u201d selle \u00fcle peitub andmebaasis endas. Skeem m\u00e4\u00e4ratletakse ainult andmebaasis ja mitte kusagil mujal, ja igal kliendil on sellele skeemile oma koopia, seega on t\u00e4iesti m\u00f5istlik n\u00f5uda skeemi ja selle terviklikkuse j\u00e4rgimist otse andmebaasis \u2013 seal, kus teave salvestatakse. <br \/>\nSee on vana ja isegi kulunud tarkus. Esialgsed ja unikaalsed v\u00f5tmed \u2013 need on head. V\u00e4listingimustes v\u00f5tmed \u2013 head. Piirangute kontroll \u2013 hea. <noindex><a rel=\"nofollow\" href=\"https:\/\/community.oracle.com\/ideas\/13028\">Kinnitus<\/a><\/noindex> \u2013 on hea. <\/p>\n<p>Kuid see pole veel k\u00f5ik. N\u00e4iteks kasutades Oracle'i, soovite t\u00f5en\u00e4oliselt n\u00e4idata:<\/p>\n<ul>\n<li>Millises tabeliruumi teie tabel asub <\/li>\n<li>Milline on selle PCTFREE v\u00e4\u00e4rtus <\/li>\n<li>Kui suur on teie j\u00e4rjestuse vahem\u00e4lu (ID taga)<\/li>\n<\/ul>\n<p>\nV\u00f5ib-olla pole see k\u00f5ik v\u00e4ikestes s\u00fcsteemides oluline, kuid ei pea ootama \u201esuurte andmete\u201d valdkonda sisenemist \u2014 v\u00f5ib hakata varakult kasutama andmete salvestamise pakkuja poolt pakutud optimeerimist, nagu \u00fclal mainitud. \u00dckski ORM, mida olen n\u00e4inud (sealhulgas jOOQ), ei paku juurdep\u00e4\u00e4su kogu DDL valikute komplektile, mida v\u00f5iksite oma andmebaasis kasutada. ORM-id pakuvad m\u00f5ningaid t\u00f6\u00f6riistu, mis aitavad DDL-i kirjutada.<\/p>\n<p>Aga l\u00f5puks, h\u00e4sti kavandatud skeem on k\u00e4sitsi kirjutatud DDL. Iga genereeritud DDL on lihtsalt selle l\u00e4hedane j\u00e4ljend.<\/p>\n<h4>Kuidas on kliendimudeliga?<\/h4>\n<p>\nNagu eelnevalt mainitud, vajate kliendil oma andmebaasi skeemi koopia, kliendi vaade. \u00dcksikasjad on kindlasti paar korda mainitud, see kliendi vaade peab olema s\u00fcnkroonitud tegeliku mudeliga. Kuidas seda k\u00f5ige paremini saavutada? Koodi generaatori abil.<\/p>\n<p>K\u00f5ik andmebaasid pakuvad oma metaandmeid SQL-i kaudu. Siin on, kuidas oma andmebaasist k\u00f5iki tabeleid erinevates SQL-i dialektides saada:<\/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>\nNeed p\u00e4ringud (v\u00f5i sarnased, s\u00f5ltuvalt sellest, kas tuleb arvesse v\u00f5tta ka vaateid, materialiseeritud vaateid, tabeli v\u00e4\u00e4rtusi funktsioone) t\u00e4idetakse samuti kutsumisega <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> JDBC-st v\u00f5i meta-mooduli jOOQ abil.<\/p>\n<p>Selliste p\u00e4ringute tulemustest on suhteliselt lihtne genereerida mis tahes kliendi vaade teie andmebaasi mudelile, s\u00f5ltumata sellest, millist tehnoloogiat kasutate.<\/p>\n<ul>\n<li>Kui kasutate JDBC-d v\u00f5i Springi, siis saate luua stringide konstantide kogumi <\/li>\n<li>Kui kasutate JPA-d, siis v\u00f5ite generiseerida ise \u00fchikut <\/li>\n<li>Kui kasutate jOOQ-i, siis saate genereerida jOOQ-i meta-mudeli<\/li>\n<\/ul>\n<p>\nS\u00f5ltuvalt sellest, kui palju v\u00f5imalusi teie kliendi API pakub (nt jOOQ v\u00f5i JPA), v\u00f5ib genereeritud meta-mudel olla t\u00f5eliselt rikka ja t\u00e4ielik. V\u00f5tame n\u00e4iteks vaikimisi liitmise v\u00f5imaluse, <noindex><a rel=\"nofollow\" href=\"https:\/\/blog.jooq.org\/2018\/02\/20\/type-safe-implicit-join-through-path-navigation-in-jooq-3-11\/\">mis ilmus jOOQ versioonis 3.11<\/a><\/noindex>, mis tugineb genereeritud metaandmetele v\u00e4liste v\u00f5tmete suhete kohta, mis kehtivad teie tabelite vahel.<\/p>\n<p>N\u00fc\u00fcd toob iga andmebaasi suurenemine automaatselt kaasa kliendikoodi uuendamise. Kujutage ette, n\u00e4iteks:<\/p>\n<pre><code class=\"sql\">ALTER TABLE book RENAME COLUMN title TO book_title;<\/code><\/pre>\n<p>\nKas t\u00f5esti soovite seda t\u00f6\u00f6d kaks korda teha? Absoluutselt mitte. Lihtsalt salvestame DDL, t\u00f6\u00f6tleme seda teie ehitusprotsessis ja saame uuendatud entiteedi:<\/p>\n<pre><code class=\"java\">@Entity\n@Table(name = \"book\", indexes = {\n \n  \/\/ Oled selle \u00fcle m\u00f5elnud?\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>\nV\u00f5i uuendatud jOOQ klass. Enamik DDL muudatusi kajastuvad ka semantikas, mitte ainult s\u00fcntaksis. Seet\u00f5ttu v\u00f5ib olla mugav vaadata kompileeritud koodis, milline kood saab (v\u00f5i v\u00f5ib) teie andmebaasi suurenemise t\u00f5ttu m\u00f5jutatud.<\/p>\n<h4>Ainult \u00fcks t\u00f5de<\/h4>\n<p>\n\u00dcksk\u00f5ik, millist tehnoloogiat kasutate, on alati olemas \u00fcks mudel, mis on mingi alams\u00fcsteemi ainus t\u00f5eallikas - v\u00f5i v\u00e4hemalt peaksime seda p\u00fc\u00fcdma teha ja v\u00e4ltima sellist ettev\u00f5tte segadust, kus \"t\u00f5de\" on korraga igal pool ja mitte kuskil. K\u00f5ik v\u00f5iks olla palju lihtsam. Kui vahetate lihtsalt XML-faile m\u00f5ne muu s\u00fcsteemiga, siis kasutage lihtsalt XSD-d. Vaadake jOOQ meta-mudelit INFORMATION_SCHEMA XML-vormis:<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 on h\u00e4sti arusaadav<\/li>\n<li>XSD m\u00e4rgib XML-i sisu v\u00e4ga h\u00e4sti ja v\u00f5imaldab valideerimist k\u00f5igis kliendikeeltes <\/li>\n<li>XSD-l on hea versioonihaldus ja arenenud tagasi\u00fchilduvus <\/li>\n<li>XSD-d saab Java koodiks t\u00f5lkida kasutades XJC-d<\/li>\n<\/ul>\n<p>\nViimane punkt on oluline. Suheldes v\u00e4list s\u00fcsteemiga XML-s\u00f5numite kaudu, tahame olla kindlad s\u00f5numite kehtivuses. Seda on v\u00e4ga lihtne saavutada JAXB, XJC ja XSD abil. Oleks t\u00e4ielik hullumeelsus loota, et \u201eJava-esimene\u201c l\u00e4henamine, kus loome oma s\u00f5numid Java objektide kujul, saaks mingil viisil m\u00f5istetavalt XML-iks muuta ja edastada teise s\u00fcsteemi tarbimiseks. Sellega genereeritud XML oleks v\u00e4ga halva kvaliteediga, dokumenteerimata ning seda oleks keeruline arendada. Kui sellise liidese puhul oleks kvaliteedi teenuse taseme (SLA) leping, oleksime selle kohe rikkunud.<\/p>\n<p>Ausalt \u00f6eldes juhtub see pidevalt JSON API-dega, kuid see on juba teine lugu, j\u00e4rgmine kord r\u00e4\u00e4gin veel... <\/p>\n<h4>Andmebaasid: see on sama asi<\/h4>\n<p>\nAndmebaasidega t\u00f6\u00f6tades m\u00f5istate, et need k\u00f5ik on p\u00f5him\u00f5tteliselt sarnased. Andmebaas haldab oma andmeid ja peab juhtima skeemi. Skeemi muudatused tuleb viia ellu otse DDL-is, et uuendada \u00fchte t\u00f5e allikat.<\/p>\n<p>Kui allika uuendamine on toimunud, peavad k\u00f5ik kliendid samuti oma mudelid uuendama. M\u00f5ned kliendid v\u00f5ivad olla kirjutatud Java keeles, kasutades jOOQ-d ja Hibernate'i v\u00f5i JDBC-d (v\u00f5i k\u00f5iki neid korraga). Teised kliendid v\u00f5ivad olla kirjutatud Perl'is (soovime neile just head \u00f5nne), kolmandad - C#-s. See ei ole oluline. Peamine mudel asub andmebaasis. ORM-i abil genereeritud mudelid on tavaliselt halvasti kvaliteetsed, halvasti dokumenteeritud ja neid on raske arendada.<\/p>\n<p>Seet\u00f5ttu \u00e4rge tehke vigu. Alustage \u00f5igesti. T\u00f6\u00f6delge andmebaasist l\u00e4htuvalt. Looge selline juurutusprotsess, mida saab automatiseerida. Lisage koodigeneraatorid, et mugavalt kopeerida oma andmebaasi mudelit ja edastada seda klientidele. Ja l\u00f5petage koodigeneraatorite muretsemine. Need on head. Nende abil saate produktiivsemaks. Peate vaid alguses natuke aega nende seadistamiseks kulutama \u2013 ja siis ootavad teid aastaid suurenenud tootlikkust, millest kujuneb teie projekti lugu.<\/p>\n<p>\u00c4rge t\u00e4nage veel, hiljem.<\/p>\n<h4>Selgitus<\/h4>\n<p>\nSelguse huvides: see artikkel ei propageeri mingil moel, et teie andmebaasi mudel peaks kogu s\u00fcsteemi painutama (st, teemaala, \u00e4ri loogika jne). Selles artiklis r\u00e4\u00e4gin ma sellest, et kliendi kood, mis suhtleb andmebaasiga, peaks toimima andmebaasi mudelilt l\u00e4htuvalt, et mitte kopeerida andmebaasi mudelit \"esimese klassi\" staatusesse. Selline loogika asub tavaliselt teabe juurdep\u00e4\u00e4su tasemel teie kliendis.<\/p>\n<p>Kaksitasandilistes arhitektuurides, mis on siiani m\u00f5nes kohas s\u00e4ilinud, v\u00f5ib selline s\u00fcsteemi mudel olla ainus v\u00f5imalus. Siiski, enamikus s\u00fcsteemides tundub andmete juurdep\u00e4\u00e4su tase olevat \u201ealams\u00fcsteem\u201d, mis kapseldab endas andmebaasi mudelit.<\/p>\n<h4>Erandid<\/h4>\n<p>\nIgal reeglil on erandeid ja olen juba \u00f6elnud, et andmebaasi esmaj\u00e4rjekorras ja l\u00e4htekoodi genereerimise l\u00e4henemine v\u00f5ib m\u00f5nikord olla sobimatu. Siin on paar sellist erandit (ilmselt on ka teisi):<\/p>\n<ul>\n<li>Kui skeem ei ole teada ja seda tuleb avada. N\u00e4iteks, kui olete t\u00f6\u00f6riista pakkuja, mis aitab kasutajatel navigeerida mistahes skeemis. Uff. Siin ei saa k\u00fcll ilma koodi genereerimiseta hakkama. Kuid siiski - andmebaas tuleb k\u00f5igepealt.<\/li>\n<li>Kui skeem peab jooksvalt genereerima mingi \u00fclesande lahendamiseks. See n\u00e4ide tundub olevat natuke keeruline versioon mustrist <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Entity%E2%80%93attribute%E2%80%93value_model\">entity attribute value<\/a><\/noindex>, st teil ei ole t\u00f5eliselt m\u00e4\u00e4ratletud skeemi. Sel juhul ei saa tihti isegi kindel olla, et teile sobib RDBMS.<\/li>\n<\/ul>\n<p>\nErandid on olemuselt erandlikud. Enamiku RDBMS-iga seotud juhtumite puhul on skeem ette teada, see asub RDBMS-is ja on ainus \"t\u00f5de\"; k\u00f5ik kliendid peavad selle p\u00f5hjal endale omandama koopiad, mis saadud sellest. Ideaalis tuleks kasutada koodigeneraatorit.<br \/>\n<br \/>Allikas: <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.1.1 - 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\/et\/blog\/administrirovanie\/istina-prezhde-vsego-ili-pochemu-sistemu-nuzhno-proektirovat-ishodya-iz-ustrojstva-bazy-dannyh\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\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\/et\/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\udd47T\u00f5de tuleb k\u00f5igepealt, v\u00f5i miks s\u00fcsteemi tuleks projekteerida l\u00e4htudes andmebaasi seadmest | ProHoster","description":"Tere, Habr! J\u00e4tkame teema uurimist","canonical_url":"https:\/\/prohoster.info\/et\/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":"et_EE","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\/et\/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\/et\/wp-json\/wp\/v2\/posts\/79465","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=79465"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/79465\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/79466"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=79465"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=79465"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=79465"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}