Kamatuoran una, o ngano nga ang sistema kinahanglan nga gidisenyo base sa aparato sa database

Hoy Habr!

Nagpadayon kami sa pagsusi sa hilisgutan Java ΠΈ Springlakip sa lebel sa database. Karon nagtanyag kami nga basahon kung ngano, kung nagdesinyo sa dagkong mga aplikasyon, kini ang istruktura sa database, ug dili ang Java code, kinahanglan nga hinungdanon nga hinungdanon, kung giunsa kini nahimo, ug unsa ang mga eksepsiyon niini nga lagda.

Niining medyo ulahi nga artikulo, akong ipasabut kung ngano nga sa akong hunahuna nga sa halos tanan nga mga kaso, ang modelo sa datos sa usa ka aplikasyon kinahanglan nga gidisenyo "gikan sa database" kaysa "gikan sa mga kapabilidad sa Java" (o bisan unsang sinultian sa kliyente nga imong gigamit. nagtrabaho uban). Pinaagi sa pagpili sa ikaduhang pamaagi, mosulod ka sa taas nga dalan sa kasakit ug pag-antos sa higayon nga ang imong proyekto magsugod sa pagtubo.

Ang artikulo gisulat base sa usa ka pangutana, gihatag sa Stack Overflow.

Makapaikag nga mga diskusyon sa reddit sa mga seksyon /r/java ΠΈ /r/pagprograma.

Pagmugna sa code

Natingala kaayo ko nga adunay ingon ka gamay nga layer sa mga tiggamit nga, nga nakaila sa jOOQ, nasuko sa kamatuoran nga ang jOOQ seryoso nga nagsalig sa henerasyon sa gigikanan nga code aron modagan. Walay nagpugong kanimo sa paggamit sa jOOQ sa paagi nga imong nakita nga angay, ug walay usa nga nagpugos kanimo sa paggamit sa code generation. Apan pinaagi sa default (sama sa gihulagway sa manwal), ang jOOQ molihok sama niini: magsugod ka sa usa ka (kabilin) ​​database schema, reverse engineer kini gamit ang jOOQ code generator aron makakuha og set sa mga klase nga nagrepresentar sa imong mga lamesa, ug dayon isulat type- luwas nga mga pangutana batok niini nga mga lamesa:

	for (Record2<String, String> record : DSL.using(configuration)
//   ^^^^^^^^^^^^^^^^^^^^^^^ Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ ΠΎ Ρ‚ΠΈΠΏΠ°Ρ… Π²Ρ‹Π²Π΅Π΄Π΅Π½Π° Π½Π° 
//   основании сгСнСрированного ΠΊΠΎΠ΄Π°, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ссылаСтся ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ΅
// Π½ΠΈΠΆΠ΅ условиС SELECT 
 
       .select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
//           vvvvv ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^ сгСнСрированныС ΠΈΠΌΠ΅Π½Π°
       .from(ACTOR)
       .orderBy(1, 2)) {
    // ...
}

Ang code gihimo bisan sa mano-mano sa gawas sa pagtukod, o sa mano-mano sa matag pagtukod. Pananglitan, ang ingon nga pagbag-o mahimong mosunod dayon pagkahuman Flyway database migration, nga mahimo usab nga mano-mano o awtomatiko.

Pagmugna sa source code

Adunay lainlaing mga pilosopiya, mga bentaha ug mga disbentaha nga nalangkit sa kini nga mga pamaagi sa paghimo sa code - manwal ug awtomatiko - nga dili nako hisgutan sa detalye sa kini nga artikulo. Apan, sa kinatibuk-an, ang tibuok nga punto sa namugna nga kodigo mao nga kini nagtugot kanimo sa pagkopya sa Java sa "kamatuoran" nga atong gipasagdan, bisan sulod sa atong sistema o sa gawas niini. Sa usa ka diwa, ang mga compiler nga nagmugna og bytecode, machine code, o uban pang matang sa code gikan sa source code nagbuhat sa samang butang - kita makakuha og representasyon sa atong "kamatuoran" sa laing pinulongan, bisan unsa pa ang piho nga mga rason.

Adunay daghang ingon nga mga generator sa code. Pananglitan, Ang XJC makahimo og Java code base sa XSD o WSDL files. Ang prinsipyo kanunay nga parehas:

  • Adunay pipila ka kamatuoran (internal o eksternal) - pananglitan, usa ka detalye, usa ka modelo sa datos, ug uban pa.
  • Nagkinahanglan kami og lokal nga representasyon niini nga kamatuoran sa among programming language.

Dugang pa, hapit kanunay nga gitambagan ang paghimo sa ingon nga representasyon - aron malikayan ang pag-usab.

Type Providers ug Annotation Processing

Mubo nga sulat: Ang lain, mas moderno ug espesipikong pamaagi sa paghimo og code alang sa jOOQ naglakip sa paggamit sa mga tighatag sa tipo, ingon nga kini gipatuman sa F #. Sa kini nga kaso, ang code gihimo sa compiler, sa tinuud sa yugto sa pagtipon. Sa prinsipyo, ang ingon nga code wala maglungtad sa porma sa mga source code. Sa Java, adunay parehas, bisan kung dili ingon ka elegante, mga himan - kini ang mga processor sa anotasyon, pananglitan, Lombok.

Sa usa ka piho nga diwa, ang parehas nga mga butang mahitabo dinhi sama sa una nga kaso, gawas:

  • Dili nimo makita ang namugna nga code (tingali kini nga sitwasyon dili ingon og salawayon sa usa ka tawo?)
  • Kinahanglan nimong sigurohon nga ang mga tipo mahimong mahatag, nga mao, ang "tinuod" kinahanglan kanunay nga magamit. Kini mao ang sayon ​​sa kaso sa Lombok, nga annotates "kamatuoran". Mas lisud kini sa mga modelo sa database nga nagdepende sa usa ka live nga koneksyon nga kanunay magamit.

Unsa ang problema sa paghimo sa code?

Dugang pa sa malisud nga pangutana kung giunsa nga mas maayo nga magsugod sa paghimo sa code - sa mano-mano o awtomatiko, kinahanglan nakong hisgutan nga adunay mga tawo nga nagtuo nga ang henerasyon sa code dili kinahanglan. Ang katarungan alang sa kini nga punto sa panan-aw, nga kanunay nakong nakit-an, mao nga lisud ang pag-set up sa pipeline sa pagtukod. Oo, lisud gyud. Adunay dugang nga gasto sa imprastraktura. Kung nagsugod ka pa lang sa usa ka partikular nga produkto (mahimo nga jOOQ, o JAXB, o Hibernate, ug uban pa), nagkinahanglag oras aron ma-set up ang usa ka workbench nga gusto nimong igugol sa pagkat-on sa API mismo aron makuha ang kantidad gikan niini. .

Kung ang mga gasto nga may kalabutan sa pagsabut sa aparato sa generator labi ka taas, nan, sa tinuud, ang API naghimo usa ka dili maayo nga trabaho sa usability sa code generator (ug sa umaabot kini nahimo nga ang pag-customize niini lisud usab). Ang pagkagamit kinahanglan mao ang labing taas nga prayoridad alang sa bisan unsang ingon nga API. Apan kana usa ra ka argumento batok sa paghimo sa code. Kay kon dili, isulat sa tibuok kamot ang lokal nga representasyon sa internal o eksternal nga kamatuoran.

Daghan ang moingon nga wala silay panahon sa pagbuhat niining tanan. Naa na sila sa deadline sa ilang Super Product. Sa umaabot nga adlaw magsuklay kami sa mga conveyor sa asembliya, adunay oras kami. Tubagon ko sila:

Kamatuoran una, o ngano nga ang sistema kinahanglan nga gidisenyo base sa aparato sa database
Orihinal, Alan O'Rourke, Audience Stack

Apan sa Hibernate / JPA dali ra kaayo isulat ang code "sa Java".

Tinuod. Alang sa Hibernate ug sa mga tiggamit niini, kini usa ka kaayohan ug usa ka tunglo. Sa Hibernate, mahimo nimong isulat ang usa ka magtiayon nga mga entidad, sama niini:

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

Ug hapit tanan andam na. Karon ang daghang Hibernate mao ang paghimo og mga komplikado nga "mga detalye" kung giunsa paghubit ang kini nga entidad sa DDL sa imong "diyalekto" sa SQL:

	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);

... ug magsugod sa pagpadagan sa aplikasyon. Usa ka maayo kaayo nga bahin aron dali nga makabangon ug makasulay sa lainlaing mga butang.

Hinuon, tugoti ko. Namakak ko.

  • Tinuod ba nga ipatuman sa Hibernate ang kahulugan niining ginganlan nga panguna nga yawe?
  • Makahimo ba ang Hibernate og indeks sa TITLE? Nasayod ko nga gikinahanglan nato kini.
  • Himoon ba sa Hibernate kini nga yawe nga yawe sa pag-ila sa Identity Specification?

Murag dili. Kung imong gipalambo ang imong proyekto gikan sa wala, kanunay nga dali nga isalikway ang daan nga database ug maghimo usa ka bag-o sa diha nga imong idugang ang kinahanglan nga mga anotasyon. Mao nga, ang entidad sa Libro sa kadugayan magkuha sa porma:

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

Bugnaw. Magbag-o. Pag-usab, sa kini nga kaso, kini mahimong labi ka dali sa pagsugod.

Apan kinahanglan nimo nga bayran kini sa ulahi.

Sa madugay o sa madali kinahanglan ka nga moadto sa produksiyon. Kana kung ang modelo mohunong sa pagtrabaho. Tungod kay:

Sa produksiyon, dili na mahimo, kung gikinahanglan, nga isalikway ang daan nga database ug sugdan ang tanan gikan sa wala. Ang imong database mahimong usa ka kabilin.

Sukad karon ug hangtod sa kahangtoran kinahanglan ka nga magsulat DDL migration scripts, eg gamit ang Flyway. Ug unsa ang mahitabo sa imong mga entidad sa kini nga kaso? Mahimo nimo nga ipahaum sila sa mano-mano (ug doblehon ang imong workload) o ipa-regenerate kini sa Hibernate alang kanimo (unsa ka posibilidad nga ang usa nga gihimo niini nga paagi aron matubag ang imong mga gilauman?) Mapildi ka bisan asa.

Busa, sa diha nga mobalhin ka sa produksiyon, kinahanglan nimo ang mainit nga mga patch. Ug sila kinahanglan nga dad-on ngadto sa produksyon kaayo sa madali. Tungod kay wala ka makaandam ug organisado nga hapsay nga pipelining sa imong mga paglalin alang sa produksiyon, nag-patch ka nga ihalas. Ug unya wala ka'y ​​panahon sa pagbuhat sa tanan nga husto. Ug gikasab-an nimo si Hibernate, tungod kay kini kanunay nga sayup sa bisan kinsa, apan dili ikaw ...

Hinunoa, gikan sa sinugdanan, ang tanan mahimo unta nga hingpit nga lahi. Pananglitan, pagbutang ug lingin nga mga ligid sa usa ka bisikleta.

Database una

Ang tinuod nga "kamatuoran" sa imong database schema ug "soberanya" sa ibabaw niini anaa sa sulod sa database. Ang schema gihubit lamang sa database mismo ug wala nay lain, ug ang matag usa sa mga kliyente adunay kopya niini nga schema, mao nga kini naghimo sa hingpit nga kahulugan sa pagpatuman sa pagsunod sa schema ug sa iyang integridad, sa pagbuhat niini sa husto sa database - diin ang impormasyon gitipigan.
Kini mao ang karaan bisan hackneyed kaalam. Ang panguna ug talagsaon nga mga yawe maayo. Ang mga langyaw nga yawe maayo. Ang pagpugong sa pagsusi maayo. Mga Pahayag - Maayo.

Ug, dili lang kana. Pananglitan, gamit ang Oracle, lagmit gusto nimong ipiho:

  • Unsa nga tablespace ang imong lamesa
  • Unsa ang iyang bili sa PCTFREE
  • Unsa ang gidak-on sa cache sa imong han-ay (luyo sa id)

Ang tanan nga kini mahimo’g dili igsapayan sa gagmay nga mga sistema, apan dili kinahanglan nga maghulat hangtod sa pagbalhin sa gingharian sa "dako nga datos" - mahimo ka magsugod nga makabenepisyo gikan sa mga pag-optimize sa pagtipig nga gihatag sa vendor, sama sa nahisgutan sa ibabaw, labi ka sayo. Walay usa sa mga ORM nga akong nakita (lakip ang jOOQ) nga naghatag og access sa tibuok set sa DDL nga mga opsyon nga gusto nimong gamiton sa imong database. Nagtanyag ang mga ORM og pipila ka mga himan aron matabangan ka sa pagsulat sa DDL.

Apan sa katapusan sa adlaw, ang usa ka maayong pagkadisenyo nga laraw kay gisulat sa kamot sa DDL. Ang bisan unsang namugna nga DDL usa lamang ka banabana niini.

Unsa ang bahin sa modelo sa kliyente?

Sama sa gihisgutan sa ibabaw, sa kliyente kinahanglan nimo ang usa ka kopya sa imong database schema, ang pagtan-aw sa kliyente. Dili kinahanglan nga isulti, kini nga pagtan-aw sa kliyente kinahanglan nga nahiuyon sa tinuud nga modelo. Unsa ang labing maayong paagi aron makab-ot kini? Uban sa usa ka code generator.

Ang tanan nga mga database naghatag sa ilang meta-impormasyon pinaagi sa SQL. Ania kung giunsa pagkuha ang tanan nga mga lamesa sa lainlaing mga diyalekto sa SQL gikan sa imong database:

	-- 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

Kini nga mga pangutana (o parehas nga mga pangutana, depende kung kinahanglan nimo nga tagdon ang mga panan-aw, materyal nga pagtan-aw, mga function nga gipabilhan sa lamesa) gipatuman usab pinaagi sa pagtawag DatabaseMetaData.getTables() gikan sa JDBC, o gamit ang jOOQ meta-module.

Gikan sa mga resulta sa maong mga pangutana, sayon ​​ra ang paghimo og bisan unsang representasyon sa kilid sa kliyente sa imong modelo sa database, bisan unsa pa nga teknolohiya ang imong gigamit sa kliyente.

  • Kung naggamit ka og JDBC o Spring makahimo ka og usa ka set sa string constants
  • Kung naggamit ka og JPA, mahimo nimong mamugna ang mga entidad mismo
  • Kung naggamit ka jOOQ mahimo ka makamugna og jOOQ meta model

Depende sa kung unsa ka dako nga kapabilidad ang gitanyag sa imong kliyente nga API (eg jOOQ o JPA), ang namugna nga meta model mahimong dato ug kompleto. Tagda, pananglitan, ang posibilidad sa dili klaro nga pag-apil, gipaila sa jOOQ 3.11, nga nagsalig sa namugna nga meta-impormasyon bahin sa langyaw nga yawe nga mga relasyon tali sa imong mga lamesa.

Karon ang bisan unsang pagdugang sa database awtomatiko nga mag-update sa code sa kliyente. Hunahunaa pananglitan:

ALTER TABLE book RENAME COLUMN title TO book_title;

Gusto ba nimo nga buhaton kini nga trabaho kaduha? Sa walay kaso. Gipasalig lang namo ang DDL, ipadagan kini pinaagi sa imong build pipeline, ug kuhaa ang updated nga entidad:

@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;
}

O ang gi-update nga klase sa jOOQ. Kadaghanan sa mga pagbag-o sa DDL makaapekto usab sa mga semantiko, dili lamang sa syntax. Busa, mahimong sayon ​​​​nga makita sa gihugpong nga code kung unsa nga code ang (o mahimong) maapektuhan pinaagi sa pagdugang sa imong database.

Ang bugtong kamatuoran

Bisan unsa nga teknolohiya ang imong gigamit, kanunay adunay usa ka modelo nga mao ra ang gigikanan sa kamatuoran alang sa pipila nga subsystem - o labing menos kinahanglan naton nga paningkamutan kini ug likayan ang kalibog sa negosyo kung diin ang "kamatuoran" bisan asa ug wala sa usa ka higayon. Ang tanan mahimong mas sayon. Kung nakigbayloay ka lang sa mga XML file sa ubang sistema, gamita lang ang XSD. Tan-awa ang INFORMATION_SCHEMA meta-model sa jOOQ sa XML nga porma:
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • Ang XSD nasabtan pag-ayo
  • Gimarkahan sa XSD nga maayo ang sulud sa XML ug gitugotan ang pag-validate sa tanan nga mga sinultian sa kliyente
  • Ang XSD maayo nga bersyon ug labi ka paatras nga katugma
  • Ang XSD mahimong hubaron sa Java code gamit ang XJC

Importante ang kataposang punto. Kung nakigsulti sa usa ka eksternal nga sistema gamit ang mga mensahe sa XML, gusto namon nga masiguro nga ang among mga mensahe balido. Sayon kaayo kini nga makab-ot sa JAXB, XJC ug XSD. Makabuang gyud ang paghunahuna nga, sa usa ka pamaagi sa disenyo nga una sa Java diin gihimo namon ang among mga mensahe ingon mga butang sa Java, mahimo kini nga mahubad nga masabtan sa XML ug ipadala alang sa pagkonsumo sa lain nga sistema. Ang XML nga namugna niining paagiha dili kaayo kalidad, dili dokumentado, ug lisud i-develop. Kung adunay usa ka kasabutan sa lebel sa kalidad sa serbisyo (SLA) sa ingon nga usa ka interface, ato dayon kini nga bungkagon.

Sa tinuud, kini gyud ang mahitabo sa tanan nga oras sa JSON API, apan kana usa ka istorya, makiglalis ako sa sunod ...

Mga database: parehas sila

Ang pagtrabaho kauban ang mga database, nahibal-an nimo nga silang tanan parehas ra. Ang database nanag-iya sa datos niini ug kinahanglang modumala sa schema. Ang bisan unsang mga pagbag-o nga gihimo sa eskema kinahanglan nga direktang ipatuman sa DDL aron ang usa ka tinubdan sa kamatuoran ma-update.

Sa diha nga ang tinubdan update nahitabo, ang tanan nga mga kliyente kinahanglan usab nga update sa ilang mga kopya sa modelo. Ang ubang mga kliyente mahimong isulat sa Java gamit ang jOOQ ug Hibernate o JDBC (o pareho). Ang ubang mga kliyente mahimong isulat sa Perl (atong pangandoyon sila og suwerte), ang uban sa C#. Dili igsapayan. Ang nag-unang modelo anaa sa database. Ang mga modelo nga hinimo sa ORM kasagarang dili maayo ang kalidad, dili maayo nga dokumentado, ug lisud nga mapalambo.

Busa ayaw pagsayop. Ayaw paghimo og mga sayop gikan sa sinugdanan. Trabaho gikan sa database. Paghimo usa ka deployment pipeline nga mahimong awtomatiko. I-enable ang mga code generators aron sayon ​​nga kopyahon ang imong database model ug ilabay kini sa mga kliyente. Ug hunong sa pagkabalaka bahin sa mga generator sa code. Maayo sila. Uban kanila, ikaw mahimong mas produktibo. Ang kinahanglan nimong buhaton mao ang paggugol ug gamay nga oras sa pag-set up niini gikan sa sinugdanan, ug adunay ka mga tuig nga gipaayo nga pasundayag aron matukod ang istorya sa imong proyekto.

Ayaw pa kog pasalamat, unya.

Pagpatin-aw

Aron mahimong tin-aw: Kini nga artikulo wala sa bisan unsang paagi nagpasiugda nga ang tibuuk nga sistema (pananglitan, domain, lohika sa negosyo, ug uban pa., ug uban pa) kinahanglan nga ibalhin aron mohaum sa imong modelo sa database. Ang akong gihisgutan sa kini nga artikulo mao nga ang code sa kliyente nga nakig-uban sa usa ka database kinahanglan molihok pinasukad sa modelo sa database aron dili kini kopyahon ang modelo sa database sa kahimtang sa "unang klase". Ang ingon nga lohika kasagarang nahimutang sa layer sa pag-access sa data sa imong kliyente.

Sa duha ka lebel nga mga arkitektura, nga gipreserbar gihapon sa pipila ka mga lugar, ang ingon nga modelo sa sistema mahimo nga usa ra nga posible. Bisan pa, sa kadaghanan nga mga sistema, ang layer sa pag-access sa data ingon usa ka "subsystem" nga nag-encapsulate sa modelo sa database.

Mga pagbati

Adunay mga eksepsiyon sa matag lagda, ug giingon ko na kaniadto nga ang database una ug ang source code generation approach usahay dili angay. Ania ang pipila ka mga eksepsiyon (tingali adunay uban pa):

  • Kung ang schema wala mahibal-an ug kinahanglan nga ablihan. Pananglitan, naghatag ka usa ka himan aron matabangan ang mga tiggamit sa pag-navigate sa bisan unsang diagram. Phew. Walay code generation dinhi. Apan sa gihapon - ang database una sa tanan.
  • Sa diha nga ang usa ka sirkito kinahanglan nga namugna sa langaw sa pagsulbad sa pipila ka mga problema. Kini nga pananglitan daw usa ka gamay nga frilly nga bersyon sa pattern bili sa hiyas sa entidad, i.e., wala gyud kay klaro nga schema. Sa kini nga kaso, kasagaran dili ka makasiguro nga ang usa ka RDBMS mohaum kanimo.

Ang mga eksepsiyon kay talagsaon ra. Sa kadaghanan nga mga kaso nga naglambigit sa paggamit sa RDBMS, ang schema nahibal-an nang daan, kini anaa sa sulod sa RDBMS ug mao lamang ang tinubdan sa "kamatuoran", ug ang tanan nga mga kliyente kinahanglan nga makakuha og mga kopya nga gikan niini. Sa tinuud, kini kinahanglan nga maglakip sa usa ka code generator.

Source: www.habr.com

Idugang sa usa ka comment