真実が先、぀たりなぜデヌタベヌス構造に基づいおシステムを蚭蚈する必芁があるのか

おい、ハブル

私たちはこのテヌマに぀いお匕き続き調査を続けたす。 Java О 春デヌタベヌス レベルも含みたす。本日は、倧芏暡なアプリケヌションを蚭蚈する際に、Java コヌドではなくデヌタベヌス構造が決定的に重芁である理由、その方法、このルヌルにはどのような䟋倖があるのか​​に぀いお説明するこずをお勧めしたす。

このかなり遅れた蚘事では、ほずんどの堎合、アプリケヌションのデヌタ モデルは「Java ファヌスト」(たたは䜿甚しおいるクラむアント蚀語) ではなく「デヌタベヌス ファヌスト」で蚭蚈する必芁があるず考える理由を説明したす。 2 番目のアプロヌチを遞択するず、プロゞェクトが成長し始めたずきに、長い苊痛ず苊悩の道を歩むこずになりたす。

この蚘事は 䞀぀の質問、Stack Overflow で質問されたした。

Redditでの興味深い議論 java の最新バヌゞョンをダりンロヌド. О / r / programming.

コヌド生成

jOOQ を知った埌、jOOQ が動䜜するために゜ヌス コヌド生成に倧きく䟝存しおいるずいう事実に憀慚するナヌザヌがごく少数いるこずに、私はずおも驚いおいたす。あなたが適切だず思う方法で jOOQ を䜿甚するこずを劚げる人はいたせんし、コヌド生成を䜿甚するこずを匷制する人もいたせん。しかし、デフォルトではマニュアルに蚘茉されおいるように、jOOQ は、レガシヌデヌタベヌス スキヌマから始めお、jOOQ コヌド ゞェネレヌタヌを䜿甚しおリバヌス ゚ンゞニアリングし、テヌブルを衚すクラスのセットを取埗し、それらのテヌブルに察しお型安党なク゚リを蚘述したす。

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

コヌドはビルド倖で手動で生成されるか、ビルドごずに手動で生成されたす。䟋えば、このような再生は、 Flywayデヌタベヌス移行は手動たたは自動で実行できたす.

゜ヌスコヌドの生成

コヌド生成に察するこれらのアプロヌチ手動ず自動には、さたざたな哲孊、利点、および欠点がありたすが、この蚘事では詳现には説明したせん。しかし、䞀般的に、生成されたコヌドの重芁な点は、システム内倖で圓然のこずず思っおいる「真実」を Java で再珟できるこずです。ある意味、これはコンパむラが゜ヌス コヌドからバむトコヌド、マシン コヌド、たたはその他の皮類のコヌドを生成するずきに行うこずです。぀たり、䜕らかの理由で、別の蚀語で「真実」の衚珟が埗られるのです。

このようなコヌドゞェネレヌタヌは数倚くありたす。䟋えば、 XJC は、XSD たたは WSDL ファむルから Java コヌドを生成できたす。。原則は垞に同じです。

  • 䜕らかの真実内郚たたは倖郚が存圚したす。たずえば、仕様、デヌタ モデルなどです。
  • 私たちのプログラミング蚀語では、この真実をロヌカルに衚珟する必芁がありたす。

さらに、冗長性を避けるために、このような衚珟を生成するこずがほずんどの堎合に掚奚されたす。

型プロバむダヌず泚釈凊理

泚: jOOQのコヌド生成に察するもう1぀のより珟代的で具䜓的なアプロヌチは、型プロバむダを䜿甚するこずです。 F#で実装されおいるので。この堎合、コヌドは実際にはコンパむル段階でコンパむラによっお生成されたす。゜ヌス圢匏では、原則ずしおそのようなコヌドは存圚したせん。 Javaには、アノテヌションプロセッサず呌ばれる、あたり゚レガントではないが類䌌のツヌルがある。 チリ.

ある意味、最初のケヌスず同じこずがここでも起こっおいたすが、次の点が異なりたす。

  • 生成されたコヌドは衚瀺されたせん (この状況は、誰かにずっおそれほど䞍快ではないず思われるかもしれたせん)
  • 型が提䟛可胜であるこず、぀たり「真実」が垞に利甚可胜であるこずを確認する必芁がありたす。 「真実」を泚釈するロンボクの堎合、これは簡単です。操䜜が垞に利甚可胜なラむブ接続に䟝存するデヌタベヌス モデルの堎合、状況は少し耇雑になりたす。

コヌド生成の問題は䜕ですか?

コヌド生成を手動で実行するか、自動で実行するかずいう難しい問題に加えお、コヌド生成はたったく必芁ないず考える人がいるこずも蚀及する䟡倀がありたす。私が最も頻繁に遭遇したこの芳点の正圓性は、ビルド パむプラむンを蚭定するのが難しいずいうこずです。はい、本圓に難しいです。远加のむンフラストラクチャコストが発生したす。特定の補品 (jOOQ、JAXB、Hibernate など) を䜿い始めたばかりの堎合は、䜜業環境の蚭定に時間がかかるため、その時間を API 自䜓の孊習に費やしお䟡倀を匕き出す方がよいでしょう。

ゞェネレヌタヌの構造を理解するためのコストが高すぎる堎合、API はコヌド ゞェネレヌタヌを䜿いやすくする䞊で実際には䞍十分な圹割を果たしおいるこずになりたす (埌でカスタマむズも難しいこずが刀明したす)。このような API では、䜿いやすさが最優先事項になるはずです。しかし、これはコヌド生成に察する反論の 1 ぀にすぎたせん。それ以倖の堎合、内郚たたは倖郚の真実のロヌカル衚珟を蚘述するのは完党に手䜜業になりたす。

これらすべおを行う時間がないず蚀う人も倚いでしょう。圌らのスヌパヌ補品の締め切りは迫っおいたす。埌で組立ラむンを培底的に調べる぀もりです。時間はありたすから。私は圌らに答えたす

真実が先、぀たりなぜデヌタベヌス構造に基づいおシステムを蚭蚈する必芁があるのか
オリゞナル, アラン・オルヌク、オヌディ゚ンス・スタック

しかし、Hibernate/JPA では「Java」コヌドを曞くのは非垞に簡単です。

本圓に。 Hibernate ずそのナヌザヌにずっお、これは祝犏であるず同時に呪いでもありたす。 Hibernate では、次のようにいく぀かの゚ンティティを簡単に蚘述できたす。

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

そしおほがすべおの準備が敎いたした。ここで、この゚ンティティが SQL 「方蚀」の DDL でどのように定矩されるかずいう耇雑な「詳现」を生成するのは、Hibernate の圹割です。

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

 そしおアプリケヌションの実行を開始したす。すぐに始めおさたざたなこずを詊すこずができる、本圓に玠晎らしい機胜です。

しかし、蚱しおください。嘘を぀きたした。

  • Hibernate は実際にこの名前付き䞻キヌ定矩を匷制するのでしょうか?
  • Hibernate は TITLE にむンデックスを䜜成したすか? - 確かに必芁になるず思いたす。
  • Hibernate は、Identity 仕様でこのキヌを確実に識別するのでしょうか?

おそらくそうではないでしょう。プロゞェクトを最初から開発しおいる堎合は、必芁な泚釈を远加したら、叀いデヌタベヌスを砎棄しお新しいデヌタベヌスを生成するず䟿利です。したがっお、Book ゚ンティティは最終的に次のようになりたす。

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

いいね。再床生成したす。この堎合も、最初は非垞に簡単になりたす。

ただし、埌で支払う必芁がありたす。

遅かれ早かれ、生産を開始しなければなりたせん。その時、このモデルは動䜜を停止したす。なぜなら

運甚時には、必芁に応じお叀いデヌタベヌスを砎棄しお最初からやり盎すこずはできなくなりたす。デヌタベヌスはレガシヌ デヌタベヌスになりたす。

これから先もずっずあなたは曞き続けなければならない DDL移行スクリプトFlywayなどを䜿甚。その堎合、あなたの゚ンティティはどうなるのでしょうか?手動で適応させるか䜜業が 2 倍になりたす、Hibernate に再生成を指瀺するか生成されたものが期埅どおりになる可胜性はどれくらいでしょうか、いずれにしおも負けです。

したがっお、本番環境に移行するず、ホット パッチが必芁になりたす。そしお、それらを迅速に生産に投入する必芁がありたす。本番環境ぞの移行のスムヌズなパむプラむンを準備しお蚭定しおいないため、すべおに必死にパッチを適甚しおいたす。するず、すべおを正しく行う時間がなくなっおしたいたす。そしお、い぀も誰か他の人のせいにしお、自分のせいではないからず、Hibernate を責めおしたいたす...

むしろ、最初からすべおをたったく違うやり方で実行できたはずだ。たずえば、自転車に䞞い車茪を付けたす。

たずデヌタベヌス

デヌタベヌス スキヌマの本圓の「真実」ずその「䞻暩」は、デヌタベヌス内にありたす。スキヌマはデヌタベヌス自䜓でのみ定矩され、他の堎所では定矩されたせん。たた、各クラむアントにはこのスキヌマのコピヌがあるため、スキヌマずその敎合性を匷制するには、情報が栌玍されおいるデヌタベヌス内で適切に実行するこずが理にかなっおいたす。
これは叀くお、陳腐な知恵です。䞻キヌず䞀意キヌは適切です。倖郚キヌは良いです。制玄を確認するのは良いこずです。 アサヌション - 倧䞈倫。

それだけではありたせん。たずえば、Oracle を䜿甚する堎合は、次のように指定する必芁がありたす。

  • テヌブルはどのテヌブルスペヌスにありたすか?
  • 圌女の PCTFREE 倀は䜕ですか?
  • シヌケンス内のキャッシュ サむズはどれくらいですか (ID の埌ろ)

これらすべおは小芏暡なシステムでは重芁ではないかもしれたせんが、「ビッグ デヌタ」領域に到達するたで埅぀必芁はありたせん。䞊蚘のようなベンダヌ提䟛のストレヌゞ最適化のメリットを、もっず早い段階から享受し始めるこずができたす。私が芋た ORM のどれも (jOOQ を含む)、デヌタベヌスで䜿甚する可胜性のある DDL オプションの完党なセットぞのアクセスを提䟛しおいたせん。 ORM は、DDL の蚘述に圹立぀ツヌルをいく぀か提䟛したす。

しかし、結局のずころ、適切に蚭蚈されたスキヌマは DDL で手曞きされたす。生成された DDL は、その近䌌倀にすぎたせん。

クラむアントモデルはどうですか?

前述のように、クラむアントではデヌタベヌス スキヌマのコピヌ (クラむアント ビュヌ) が必芁になりたす。蚀うたでもなく、このクラむアント ビュヌは実際のモデルず同期しおいる必芁がありたす。これを達成するための最善の方法は䜕でしょうか?コヌドゞェネレヌタヌの䜿甚。

すべおのデヌタベヌスは、SQL を介しおメタ情報を公開したす。さたざたな SQL 方蚀でデヌタベヌスからすべおのテヌブルを取埗する方法は次のずおりです。

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

これらのク゚リたたは、ビュヌ、マテリアラむズドビュヌ、テヌブル倀関数も考慮する必芁があるかどうかに応じお、同様のク゚リも、呌び出しを䜿甚しお実行されたす。 DatabaseMetaData.getTables() JDBC から、たたは jOOQ メタモゞュヌルを䜿甚しお。

このようなク゚リの結果から、クラむアントで䜿甚しおいるテクノロゞに関係なく、デヌタベヌス モデルのクラむアント偎ビュヌを生成するのは比范的簡単です。

  • JDBCたたはSpringを䜿甚しおいる堎合は、文字列定数のセットを䜜成できたす。
  • JPAを䜿甚する堎合は、゚ンティティを自分で生成できたす。
  • jOOQを䜿甚するず、jOOQメタモデルを生成できる。

クラむアント API が提䟛する機胜の量 (jOOQ や JPA など) に応じお、生成されるメタモデルは非垞に豊富で完党なものになりたす。䟋えば、暗黙の連想の可胜性を考えおみたしょう。 jOOQ 3.11で導入これは、テヌブル間に存圚する倖郚キヌ関係に関する生成されたメタ情報に䟝存したす。

今埌は、デヌタベヌスが拡倧するず、クラむアント コヌドが自動的に曎新されるようになりたす。たずえば、次のこずを想像しおください。

ALTER TABLE book RENAME COLUMN title TO book_title;

本圓にこの仕事を2回やりたいですか?いかなる堎合でも。 DDL をコミットし、ビルド パむプラむンで実行しお、曎新された゚ンティティを取埗するだけです。

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

たたは、曎新された jOOQ クラス。ほずんどの DDL の倉曎は、構文だけでなくセマンティクスにも圱響したす。したがっお、コンパむルされたコヌドを調べお、デヌタベヌスの増倧によっおどのコヌドが圱響を受けるか (たたは圱響を受ける可胜性があるか) を確認するず圹立ちたす。

唯䞀の真実

どのようなテクノロゞヌを䜿甚しおいおも、䜕らかのサブシステムの唯䞀の真実の゜ヌスずなるモデルが垞に 1 ぀存圚したす。少なくずも、私たちはそれを目指しお、「真実」がどこにでもあるず同時にどこにも存圚しないような䌁業の混乱を避ける必芁がありたす。すべおがもっずシンプルになるはずです。他のシステムず XML ファむルを亀換するだけの堎合は、XSD を䜿甚したす。 jOOQ の INFORMATION_SCHEMA メタモデルを XML 圢匏で芋おみたしょう。
https://www.jooq.org/xsd/jooq-meta-3.10.0.xsd

  • XSDはよく理解されおいる
  • XSD は XML コンテンツを非垞に適切にマヌクアップし、すべおのクラむアント蚀語での怜蚌を可胜にしたす。
  • XSD は適切にバヌゞョン管理されおおり、高床な䞋䜍互換性を備えおいたす。
  • XSDはXJCを䜿甚しおJavaコヌドに倉換できたす。

最埌の点は重芁です。 XML メッセヌゞを䜿甚しお倖郚システムず通信する堎合、メッセヌゞが有効であるこずを確認する必芁がありたす。これは、JAXB、XJC、XSD を䜿甚するず非垞に簡単に実珟できたす。メッセヌゞを Java オブゞェクトずしお䜜成する「Java ファヌスト」蚭蚈アプロヌチを採甚した堎合、メッセヌゞを意味のある方法で XML にマッピングし、別のシステムに送信しお䜿甚できるず期埅するのはたったくの狂気です。この方法で生成された XML は、品質が非垞に䜎く、文曞化されおおらず、進化が困難になりたす。このようなむンタヌフェヌスにサヌビス レベル契玄 (SLA) があった堎合、私たちはすぐにそれを台無しにしおいたでしょう。

正盎に蚀うず、これはたさに JSON API で垞に起こっおいるこずですが、それはたた別の話で、次回戊いたす...

デヌタベヌス同じもの

デヌタベヌスを操䜜するず、それらはすべお基本的に䌌おいるこずに気づきたす。デヌタベヌスはデヌタを所有し、スキヌマを管理する必芁がありたす。スキヌマに加えられた倉曎は、唯䞀の真実の゜ヌスが曎新されるように、DDL に盎接実装する必芁がありたす。

゜ヌスの曎新が発生するず、すべおのクラむアントもモデルのコピヌを曎新する必芁がありたす。䞀郚のクラむアントは、jOOQ ず Hibernate たたは JDBC (たたはそれらすべお) を䜿甚しお Java で蚘述される堎合がありたす。他のクラむアントは Perl で曞かれおいるかもしれたせん (幞運を祈りたす)、たた他のクラむアントは C# で曞かれおいるかもしれたせん。それは問題ではありたせん。メむンモデルはデヌタベヌス内にありたす。 ORM によっお生成されるモデルは通垞、品質が䜎く、ドキュメント化が䞍十分で、進化が困難です。

だから間違いをしないでください。最初から間違いをしないでください。デヌタベヌスから䜜業したす。自動化できるデプロむメント パむプラむンを構築したす。コヌド ゞェネレヌタヌを有効にするず、デヌタベヌス モデルを簡単にコピヌしおクラむアントにダンプできるようになりたす。コヌドゞェネレヌタヌに぀いお心配する必芁はもうありたせん。それらは良いです。それらを䜿甚するず、生産性が向䞊したす。最初から少し時間をかけお蚭定するだけで、プロゞェクトのストヌリヌを圢䜜る生産性の向䞊を䜕幎にもわたっお享受できたす。

ただ感謝しないでください。埌で感謝しおください。

明確化

明確に述べたすず、この蚘事は、デヌタベヌス モデルに合わせおシステム党䜓 (぀たり、サブゞェクト領域、ビゞネス ロゞックなど) を倉曎する必芁があるず䞻匵するものではありたせん。この蚘事では、デヌタベヌスず察話するクラむアント コヌドは、それ自䜓がファヌストクラスの状態でデヌタベヌス モデルを再珟しないように、デヌタベヌス モデルず䞀貫性のある方法で動䜜する必芁があるこずを䞻匵したす。このロゞックは通垞、クラむアントのデヌタ アクセス局に配眮されたす。

䞀郚の堎所では䟝然ずしお 2 局アヌキテクチャが残っおいたすが、そのようなシステム モデルが唯䞀可胜なモデルである可胜性がありたす。しかし、ほずんどのシステムでは、デヌタ アクセス局はデヌタベヌス モデルをカプセル化する「サブシステム」であるように思われたす。

䟋倖

すべおのルヌルには䟋倖があり、デヌタベヌスファヌスト、゜ヌスコヌド生成のアプロヌチが䞍適切になる堎合があるこずはすでに述べたした。以䞋に、そのような䟋倖をいく぀か瀺したす (おそらく他にも䟋倖はありたす)。

  • 回路が䞍明で発芋する必芁がある堎合。たずえば、ナヌザヌが任意の図をナビゲヌトするのに圹立぀ツヌルを提䟛しおいるずしたす。ふう。ここではコヌド生成は行われたせん。しかし、やはりデヌタベヌスが最優先です。
  • 䜕らかの問題を解決するために回路を即座に生成する必芁がある堎合。この䟋は、パタヌンの少し掟手なバヌゞョンのように思えたす。 ゚ンティティ属性倀぀たり、明確に定矩されたスキヌムが実際には存圚しないずいうこずです。この堎合、RDBMS が適切であるかどうかを確認するこずは䞍可胜であるこずがよくありたす。

䟋倖は本質的に䟋倖的なものである。 RDBMS が関係するほずんどの堎合、スキヌマは事前にわかっおおり、RDBMS 内に存圚し、唯䞀の「真実」の゜ヌスであり、すべおのクラむアントはそこから掟生したコピヌを取埗する必芁がありたす。理想的には、これにはコヌド ゞェネレヌタヌを䜿甚する必芁がありたす。

出所 habr.com

DDoS 保護機胜を備えた信頌性の高いサむト甚ホスティング、VPS VDS サヌバヌを賌入する 🔥 DDoS攻撃察策付きの信頌性の高いりェブサむトホスティング、VPS/VDSサヌバヌを賌入したしょう | ProHoster