Pêşî rastî, an çima pêdivî ye ku pergalek li ser bingeha sêwirana databasê were sêwirandin

Hey Habr!

Em lêkolîna mijarê berdewam dikin Java и Bihar, di asta databasê de jî. Îro em we vedixwînin ku hûn bixwînin ka çima, dema sêwirana serîlêdanên mezin, ew strukturê databasê ye, û ne koda Java, ya ku girîngiyek diyarker e, ev çawa tête kirin, û çi îstîsnayên vê qaîdeyê hene.

Di vê gotara pir dereng de, ez ê rave bikim ka çima ez bawer dikim ku hema hema di hemî rewşan de, modela daneyê ya di serîlêdanê de divê "ji databasê" were sêwirandin ne ji "ji kapasîteyên Java" (an ji kîjan zimanê xerîdar ku hûn lê ne. bi xebitîn). Bi girtina nêzîkatiya duyemîn, hûn gava ku projeya we dest bi mezinbûnê dike, hûn xwe ji bo rêyek dirêj a êş û azarê saz dikin.

Gotar li ser bingeha hatiye nivîsandin yek pirs, li ser Stack Overflow tê dayîn.

Di beşan de nîqaşên balkêş ên li ser reddit /r/java и /r/bernamekirin.

nifşê kodê

Ez çiqas şaş bûm ku beşek piçûk a bikarhêneran heye ku, ji ber ku bi jOOQ re nas kirin, ji vê yekê aciz in ku jOOQ bi giranî xwe dispêre hilberîna koda çavkaniyê ku bixebite. Tu kes nahêle ku hûn jOOQ wekî ku hûn rast dibînin bikar bînin, an jî we neçar dike ku hûn hilberîna kodê bikar bînin. Lê awayê xwerû (wekî ku di destanê de hatî destnîşan kirin) xebata bi jOOQ re ev e ku hûn bi şema databasek (mîrasî) dest pê bikin, wê bi jeneratorê kodê jOOQ berevajî bikin ku bi vî rengî komek çînên ku tabloyên xwe temsîl dikin bistînin, û dûv re celebek binivîsin. -Pirsên ewledar ên van tabloyan:

	for (Record2<String, String> record : DSL.using(configuration)
//   ^^^^^^^^^^^^^^^^^^^^^^^ Информация о типах выведена на 
//   основании сгенерированного кода, на который ссылается приведенное
// ниже условие SELECT 
 
       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
//           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ сгенерированные имена
       .from(ACTOR)
       .orderBy(1, 2)) {
    // ...
}

Kod bi destan li derveyî meclîsê, an jî bi destan li her civînê tê çêkirin. Mînakî, nûvekirinek wusa dibe ku tavilê piştî wê peyda bibe Koçkirina databasa Flyway, ku dikare bi destan an bixweber jî were kirin.

Çêkirina koda çavkaniyê

Felsefe, avantaj û dezawantajên cûrbecûr hene ku bi van nêzîkatiyên ji bo hilberîna kodê - destan û otomatîk - ve girêdayî ne ku ez ê di vê gotarê de bi hûrgulî nîqaş nekim. Lê, bi gelemperî, hemî xala koda hatî hilberandin ev e ku ew destûrê dide me ku em di Java-yê de wê "rastiya" ya ku em ji xwe re digirin, di hundurê pergala xwe de an jî li derveyî wê dubare bikin. Di wateyek de, ev tiştê ku berhevkar dikin dema ku ew bytecode, koda makîneyê, an rengek din ê koda çavkaniyê diafirînin - bêyî sedemên taybetî, em nûnertiya "rastiya" xwe bi zimanek din digirin.

Gelek çêkerên kodê yên weha hene. Bo nimûne, XJC dikare koda Java-yê li ser pelên XSD an WSDL biafirîne. Prensîp her gav yek e:

  • Hin rastiyek heye (hundirîn an derveyî) - mînakek taybetmendiyek, modelek daneyê, hwd.
  • Pêdiviya me bi temsîla herêmî ya vê rastiyê di zimanê bernameya me de heye.

Wekî din, hema hema her gav tê pêşniyar kirin ku nûneriyek wusa çêbike da ku ji zêdebûnê dûr nekevin.

Pêşkêşkerên Tîp û Pêvajoya Annotation

Nîşe: Nêzîkatiyek din, nûjentir û taybetîtir ji bo afirandina kodê ji bo jOOQ peydakerên celeb bikar tîne, wek ku ew di F# de têne bicîh kirin. Di vê rewşê de, kod ji hêla berhevkerê ve, bi rastî di qonaxa berhevkirinê de tête çêkirin. Di prensîbê de, kodek wusa di forma çavkaniyê de tune. Java xwedan amûrên mîna, her çend ne xweşik, jî hene - pêvajoyên annotation, wek nimûne, Lombok.

Di wateyekê de, li vir heman tişt diqewimin wekî di doza yekem de, ji bilî:

  • Hûn koda hatî hilberandin nabînin (dibe ku ev rewş ji kesek re kêmtir rezîl xuya dike?)
  • Pêdivî ye ku hûn piştrast bikin ku celeb dikarin bêne peyda kirin, ango "rast" divê her gav peyda bibe. Ev di doza Lombok de, ku "rastiyê" vedibêje, hêsan e. Ew bi modelên databasê yên ku bi pêwendiyek zindî ya domdar ve girêdayî ye hinekî tevlihevtir e.

Pirsgirêka hilberîna kodê çi ye?

Digel pirsa dijwar ka meriv çawa çêtirîn hilberîna kodê dimeşîne - bi destan an bixweber, divê em jî bibêjin ku mirov hene ku bawer dikin ku hilberîna kodê qet ne hewce ye. Rastkirina vê nêrînê, ku ez pir caran pê re hatim, ev e ku wê hingê dijwar e ku meriv boriyek çêkirinê saz bike. Erê, bi rastî zehmet e. Lêçûnên binesaziyê yên zêde çêdibin. Ger hûn nû dest bi hilberek taybetî dikin (çi ew jOOQ, an JAXB, an Hibernate, hwd.), Sazkirina hawîrdorek hilberînê wext digire ku hûn bijare ku hûn API-yê bixwe fêr bibin da ku hûn nirxê jê derxin. .

Ger lêçûnên ku bi têgihiştina strukturên jeneratorê ve girêdayî ne pir zêde bin, wê hingê, bi rastî, API-ê li ser karanîna jeneratorê kodê karekî nebaş kir (û paşê derket holê ku xwerûkirina bikarhêner di wê de jî dijwar e). Pêdivî ye ku bikêrhatî ji bo her API-ya wusa pêşîniya herî bilind be. Lê ev tenê yek argumanek li dijî hilberîna kodê ye. Wekî din, nivîsandina nûnertiyek herêmî ya rastiya hundurîn an derveyî bi tevahî bi destan e.

Pir kes dê bibêjin ku wextê wan tune ku van tiştan bikin. Ew ji bo Hilbera xweya Super-a wan maweyan diqedin. Rojekê em ê konveyorên meclîsê paqij bikin, wextê me hebe. Ez ê bersiva wan bidim:

Pêşî rastî, an çima pêdivî ye ku pergalek li ser bingeha sêwirana databasê were sêwirandin
Eslî, Alan O'Rourke, Temaşevan Stack

Lê di Hibernate/JPA de nivîsandina koda Java-yê pir hêsan e.

Bicî. Ji bo Hibernate û bikarhênerên wê, ev hem bereket û nifir e. Di Hibernate de hûn dikarin bi tenê çend saziyan binivîsin, mîna vê:

	@Entity
class Book {
  @Id
  int id;
  String title;
}

Û hema her tişt amade ye. Naha di destê Hibernate de ye ku "hûrgiliyên" tevlihev biafirîne ka dê çawa bi rastî ev sazî di DDL-ya "zaravaya" weya SQL de were destnîşankirin:

	CREATE TABLE book (
  id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
  title VARCHAR(50),
 
  CONSTRAINT pk_book PRIMARY KEY (id)
);
 
CREATE INDEX i_book_title ON book (title);

... û dest bi xebitandina sepanê bikin. Derfetek bi rastî xweş ku hûn zû dest pê bikin û tiştên cûda biceribînin.

Lêbelê, ji kerema xwe destûrê bide min. Ez derewan dikim.

  • Dê Hibernate bi rastî pênasekirina vê mifteya bingehîn a binavkirî bicîh bîne?
  • Dê Hibernate di TITLE de indexek biafirîne? – Ez teqez dizanim ku dê hewcedariya me pê hebe.
  • Dê Hibernate tam vê mifteyê di Taybetmendiya Nasnameyê de nas bike?

Probably ne. Ger hûn projeya xwe ji sifirê pêşdixin, her gav hêsan e ku hûn databasa kevn ji holê rakin û gava ku hûn şîroveyên pêwîst lê zêde bikin yek nû çêkin. Bi vî rengî, sazûmana Pirtûkê dê di dawiyê de forma xwe bigire:

	@Entity
@Table(name = "book", indexes = {
  @Index(name = "i_book_title", columnList = "title")
})
class Book {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  int id;
  String title;
}

Xwînsar. Ji nû ve nûjen kirin. Dîsa, di vê rewşê de ew ê di destpêkê de pir hêsan be.

Lê hûn ê paşê ji bo wê bidin

Zû an dereng hûn ê neçar bibin ku biçin hilberînê. Wê demê ev model dê bisekine. Bo:

Di hilberînê de, heke hewce be, dê êdî ne mumkun be ku databasa kevn were avêtin û ji sifirê dest pê bike. Databasa we dê bibe mîras.

Ji niha û pê ve û heta hetayê divê hûn binivîsin Mînakî, nivîsarên koçberiya DDL, bi karanîna Flyway. Di vê rewşê de dê çi were serê saziyên we? Hûn dikarin wan bi destan biguhezînin (û bi vî rengî barê xebata xwe ducar bikin), an jî hûn dikarin ji Hibernate re bibêjin ku wan ji we re nûjen bike (yên ku bi vî rengî têne hilberandin çiqas e ku hêviyên we bicîh bînin?) Bi her awayî, hûn winda dikin.

Ji ber vê yekê gava ku hûn ketin hilberînê, hûn ê hewceyê pêlên germ bibin. Û pêdivî ye ku ew pir zû bêne hilberandin. Ji ber ku we ji bo hilberandinê boriyek birêkûpêk a koçberiyên xwe amade nekir û organîze nekir, hûn bi hovîtî her tiştî dişoxilînin. Û hingê êdî wextê we tune ku hûn her tiştî rast bikin. Û hûn Hibernate rexne dikin, ji ber ku ew her gav sûcê kesek din e, tenê ne hûn ...

Di şûna wê de, tişt dikaribû ji destpêkê ve bi tevahî cûda were kirin. Mînakî, çerxên dor li bîsîkletekê bixin.

Database yekem

Di şemaya databasa we de "rastiya" rast û "serweriya" wê di nav databasê de ye. Schema tenê di databasê bixwe de û li cîhek din tête diyar kirin, û her xerîdar xwedan kopiyek vê şemayê ye, ji ber vê yekê bêkêmasî maqûl e ku meriv lihevhatina bi şema û yekparebûna wê bicîh bîne, ku wê rast di databasê de bike - li ku derê agahdarî ye. depokirin.
Ev aqilmendiyek kevn e, hetta xapînok e. Bişkojkên seretayî û yekta baş in. Bişkojkên biyanî baş in. Kontrolkirina qedexeyan baş e. Assertions - Baş e.

Wekî din, ew ne hemî ye. Mînakî, bi karanîna Oracle, dibe ku hûn bixwazin diyar bikin:

  • Maseya we di kîjan sifrê de ye?
  • Nirxa wê ya PCTFREE çi ye?
  • Mezinahiya cache di rêza we de çi ye (li pişt id)

Dibe ku ev di pergalên piçûk de ne girîng be, lê hûn ne hewce ne ku li bendê bin heya ku hûn derbasî qada daneya mezin bibin - hûn dikarin zûtir dest bi sûdwergirtina ji xweşbîniyên hilanînê yên ku ji hêla firoşkar ve têne peyda kirin mîna yên ku li jor hatine destnîşan kirin, bikin. Yek ji ORM-yên ku min dîtiye (jOOQ jî tê de) gihîştina tevaya vebijarkên DDL-ya ku hûn dixwazin di databasa xwe de bikar bînin peyda nakin. ORM hin amûran pêşkêş dikin ku ji we re dibe alîkar ku hûn DDL binivîsin.

Lê di dawiya rojê de, çerxek baş-sêwirandî bi DDL-ê bi destan tê nivîsandin. Her DDL-ya hatî çêkirin tenê nêzîkatiyek wê ye.

Li ser modela xerîdar çi ye?

Wekî ku li jor behs kir, li ser xerîdar hûn ê kopiyek ji şemaya databasa xwe, dîtina xerîdar hewce bikin. Ne hewce ye ku were gotin, ev dîtina xerîdar divê bi modela rastîn re hevdeng be. Awayê çêtirîn ji bo bidestxistina vê yekê çi ye? Bikaranîna jeneratorê kodê.

Hemî databases agahdariya meta xwe bi SQL peyda dikin. Li vir e ku meriv çawa hemî tabloyan ji databasa xwe bi zaravayên cihêreng ên SQL digire:

	-- H2, HSQLDB, MySQL, PostgreSQL, SQL Server
SELECT table_schema, table_name
FROM information_schema.tables
 
-- DB2
SELECT tabschema, tabname
FROM syscat.tables
 
-- Oracle
SELECT owner, table_name
FROM all_tables
 
-- SQLite
SELECT name
FROM sqlite_master
 
-- Teradata
SELECT databasename, tablename
FROM dbc.tables

Van pirsan (an jî yên mîna, li gorî ka divê hûn nerîn, dîtinên materyalkirî, fonksiyonên bi nirx-tabloyê jî bihesibînin) jî bi bangkirinê têne darve kirin. DatabaseMetaData.getTables() ji JDBC, an jî meta-modula jOOQ bikar bînin.

Ji encamên pirsên weha, bi rengek hêsan e ku meriv her nûneriya xerîdar a modela databasa xwe biafirîne, bêyî ku hûn çi teknolojiyê li ser xerîdar bikar tînin.

  • Heke hûn JDBC an Spring bikar tînin, hûn dikarin komek domdarên rêzikê biafirînin
  • Ger hûn JPA bikar bînin, hûn dikarin saziyan bixwe biafirînin
  • Heke hûn jOOQ bikar bînin, hûn dikarin modela meta jOOQ biafirînin

Li gorî ka çiqas fonksiyon ji hêla API-ya muwekîlê we ve tê pêşkêş kirin (mînak jOOQ an JPA), modela meta ya çêkirî dikare bi rastî dewlemend û bêkêmasî be. Mînakî, îhtîmala tevlêbûna nepenî bigire, di jOOQ 3.11 de hatî destnîşan kirin, ku xwe dispêre agahdariya meta ya çêkirî di derbarê têkiliyên biyanî yên ku di navbera tabloyên we de hene.

Naha her zêdekirina databasê dê koda xerîdar bixweber nûve bike. Mînakî bifikirin:

ALTER TABLE book RENAME COLUMN title TO book_title;

Ma hûn bi rastî dixwazin vî karî du caran bikin? Di tu rewşê de. Tenê DDL-ê bicîh bikin, wê di nav lûleya avakirina xwe de bimeşînin, û saziya nûvekirî bistînin:

@Entity
@Table(name = "book", indexes = {
 
  // Вы об этом задумывались?
  @Index(name = "i_book_title", columnList = "book_title")
})
class Book {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  int id;
 
  @Column("book_title")
  String bookTitle;
}

An jî çîna jOOQ ya nûvekirî. Piraniya guhertinên DDL jî bandorê li semantîkê dikin, ne tenê hevoksaziyê. Ji ber vê yekê, ew dikare kêrhatî be ku hûn li koda berhevkirî binihêrin da ku bibînin ka kîjan kod dê (an dikare) ji zêdebûna databasa we bandor bibe.

Tenê rastî

Bêyî ku hûn kîjan teknolojiyê bikar tînin, her gav yek modelek heye ku ji bo hin bine-sîstema tenê çavkaniya rastiyê ye - an, bi kêmanî, divê em ji bo vê yekê têbikoşin û ji tevliheviya pargîdaniyek wusa dûr bixin, ku "rastî" li her derê û li tu derê yekcar e. . Her tişt dikare pir hêsantir be. Heke hûn tenê pelên XML bi pergalek din re diguhezînin, tenê XSD bikar bînin. Li meta-modela INFORMATION_SCHEMA ji jOOQ di forma XML de binihêrin:
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • XSD baş tê fêm kirin
  • XSD naveroka XML-ê pir baş tokenîze dike û bi hemî zimanên xerîdar destûrê dide pejirandinê
  • XSD guhertoyek baş e û lihevhatina paşverû ya pêşkeftî heye
  • XSD dikare bi karanîna XJC di koda Java de were wergerandin

Xala dawî girîng e. Dema ku bi pergalek derveyî re bi karanîna peyamên XML re têkilî daynin, em dixwazin pê ewle bin ku peyamên me derbasdar in. Ev pir hêsan e ku meriv bi karanîna JAXB, XJC û XSD bikar bîne. Dê dînbûnek bêkêmasî be ku meriv bifikire ku, bi nêzîkatiyek sêwirana "Pêşî Java" ya ku em peyamên xwe wekî tiştên Java çêdikin, ew dikarin bi rengek hevgirtî li XML-ê werin nexşandin û ji bo vexwarinê ji pergalek din re werin şandin. XML-ya ku bi vî rengî hatî hilberandin dê bi kalîteya pir xirab, bêbelge, û pêşkeftina dijwar be. Ger ji bo pêwendiyek wusa peymanek asta karûbarê (SLA) hebûya, em ê tavilê wê xera bikin.

Bi rûmet, tiştê ku her dem bi JSON API-yên diqewime ev e, lê ew çîrokek din e, ez ê carek din biqelişe…

Database: ew heman tişt in

Dema ku bi databasan re dixebitin, hûn fêhm dikin ku ew hemî bi bingehîn mîna hev in. Bingeh xwediyê daneyên xwe ye û divê nexşeyê birêve bibe. Pêdivî ye ku guheztinek ku li şemayê hatî çêkirin rasterast di DDL de were bicîh kirin da ku çavkaniya yekane ya rastiyê were nûve kirin.

Dema ku nûvekirinek çavkaniyek çêbû, divê hemî xerîdar jî kopiyên xwe yên modelê nûve bikin. Hin xerîdar dikarin di Java-yê de bi karanîna jOOQ û Hibernate an JDBC (an hem jî) werin nivîsandin. Xerîdarên din dikarin di Perl de bêne nivîsandin (em tenê ji wan re serkeftin dixwazin), lê yên din dikarin bi C# bêne nivîsandin. Balkeş nîne. Modela sereke di databasê de ye. Modelên ku bi karanîna ORM-ê têne hilberandin bi gelemperî qalîteya qels in, kêm belgekirî ne û pêşkeftina wan dijwar e.

Ji ber vê yekê xeletiyan nekin. Ji destpêkê ve xeletiyan nekin. Kar ji databasê. Xetek birêkûpêk a ku dikare bixweber were çêkirin ava bikin. Generatorên kodê çalak bikin da ku hûn modela databasa xwe kopî bikin û wê li ser xerîdaran bihêlin. Û li ser jeneratorên kodê rawestin. Ew baş in. Bi wan re hûn ê bêtir hilberîner bibin. Hûn tenê hewce ne ku ji destpêkê ve demek hindik derbas bikin da ku wan saz bikin - û dûv re salên zêde hilberîna hilberê li benda we ne, ku dê dîroka projeya we çêbike.

Hîn ji min re spas neke, paşê.

Ravekirin

Zelal be: Ev gotar bi tu awayî parêzvaniyê nake ku hûn hewce ne ku tevahiya pergalê (ango domain, mantiqa karsaziyê, hwd., hwd.) dakêşin da ku modela databasa xwe bicîh bînin. Tiştê ku ez di vê gotarê de dibêjim ev e ku koda xerîdar a ku bi databasê re têkildar dibe divê li ser bingeha modela databasê tevbigere, da ku ew bixwe modela databasê di rewşek "pola yekem" de dubare neke. Ev mantiq bi gelemperî li qata gihîştina daneyê ya li ser muwekîlê we ye.

Di mîmariyên du-astî de, ku hîn jî li hin deveran têne parastin, modelek pergalê ya weha dibe ku yekane yeka gengaz be. Lêbelê, di pir pergalan de qata gihîştina daneyê ji min re wekî "binpergalek" xuya dike ku modela databasê vedihewîne.

Exceptions

Ji her qaîdeyê re îstîsna hene, û min berê jî gotiye ku nêzîkatiya hilberîna databasa-yekemîn û koda çavkaniyê carinan dibe ku negunca be. Li vir çend îstîsnayên weha hene (dibe ku yên din jî hene):

  • Dema ku schema nenas e û pêdivî ye ku were kifş kirin. Mînakî, hûn dabînkerek amûrek in ku ji bikarhêneran re dibe alîkar ku li her diagramekê bigerin. Ugh. Li vir hilberîna kodê tune. Lê dîsa jî, databas yekem tê.
  • Gava ku pêdivî ye ku li ser firînê çerxek were çêkirin da ku hin pirsgirêk çareser bibe. Ev nimûne wekî guhertoyek piçûk a nimûneyê xuya dike nirxa taybetmendiya entity, ango, hûn bi rastî ne xwediyê nexşeyek zelal diyarkirî ne. Di vê rewşê de, hûn pir caran ne dikarin pê bawer bin ku RDBMS dê li gorî we be.

Îstîsna bi xwezayê awarte ne. Di pir rewşan de ku bi karanîna RDBMS ve girêdayî ye, şema pêşwext tê zanîn, ew di nav RDBMS-ê de dimîne û çavkaniya yekane ya "rastiyê" ye, û hemî xerîdar neçar in ku kopiyên ku jê hatine wergirtin bistînin. Bi îdeal, hûn hewce ne ku hilberînerek kodê bikar bînin.

Source: www.habr.com

Add a comment