JavaのDAO(Data Access Object)で複数テーブルのJOINするケースってどうするのか

f:id:ts0818:20210724160516j:plain

gigazine.net

地球は、太陽系を形作った星間ガスや塵(ちり)が集まってできたものだと考えられています。そんな地球が、岩石ではなく「甘くておいしいブルーベリーでできていたら?」という素朴な疑問に、アメリカ・オックスフォード大学の科学者が真面目に取り組んだ論文が発表されました。

地球が「超巨大なブルーベリーの塊」に変わったら一体何が起きるのか? - GIGAZINE

⇧『グレートでスよ こいつはぁ~~~っ(「ジョジョの奇妙な冒険・第四部【東方仗助】」)』って思わずつぶやきたくなるぐらい、クレイジーですね~良い意味で。

というわけで、今回もJavaについてです、レッツトライ~。

 

DAO(Data Access Object)とは?

Wikipediaさんに聞いてみよう。 

Data Access ObjectDAO)とは、ある種のデータベース永続性機構の抽象化されたインタフェースを提供するオブジェクトであり、データベースの詳細を開示することなく特定の操作を提供する。

Data Access Object - Wikipedia

なお、マイクロソフトのライブラリであるData Access Objectsとは直接の関係はない。

Data Access Object - Wikipedia

⇧ ということで、超ザックリ捉えると、

  • データベース
  • 永続性機構

に対しての「処理のまとまり」 を持つ「インターフェイス」を使っていこうという考えらしいですかね。

デザインパターン」の1つらしく、

www.oracle.com

The Data Access Object (or DAO) pattern:

  • separates a data resource's client interface from its data access mechanisms
  • adapts a specific data resource's access API to a generic client interface

https://www.oracle.com/java/technologies/data-access-object.html

Oracleさんの説明でも、「The Data Access Object (or DAO) pattern:」って説明になってますね。

ちなみに、「デザインパターン」は、

ソフトウェア開発におけるデザインパターン(型紙(かたがみ)または設計パターンdesign pattern)とは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。

デザインパターン (ソフトウェア) - Wikipedia

Javaだけのものではないってことですね。

先人たちの血と汗と涙の結晶ということですかね、ありがたや~。

 

複数テーブルをJOINしたときのDAO(Data Access Object)ってどうするの?

で、意外に情報が見つからないのが、 「複数テーブルをJOINした際のDAO(Data Access Object)」ってどうすれば良いのかというね。

Oracleさんの一例によると、

⇧ 複数の「DAO: Transfer Object」をガッチャンコした「DAO: Transfer Object」を用意して、その「DAO: Transfer Object」に対応する「DAO(Data Access Object)」を用意するってことらしい。

上図の例で言うと、 

  • Page
    • Catgeory
    • Product
    • Item

っていう「DAO: Transfer Object」の関係になるみたい。

「DAO(Data Access Object)」は、

  • CategoryDAO

で、「DAO(Data Access Object)」は「インターフェイス」だから、「DAO(Data Access Object)」を実装したクラスが、

  • CloudscapeCatalogDAO

ってことみたいね。 

というか、「DAO: Transfer Object」についての説明は一切しないという、安定の不親切さが健在のOracleさん、流石です。

まぁ、おそらく「DTO(Data Transfer Object)」 のことを言ってるんだとは思うけど...

ちなみに、「DTO(Data Transfer Object)」 は、

Data Transfer ObjectDTO)はデザインパターンの一種で、アプリケーションソフトウェアのサブシステム間でデータを転送するのに使う。過去、J2EE第一版においてはValue ObjectsVO)と呼ばれていた。

Data Transfer Object - Wikipedia

なお、マーティン・ファウラーが著書「Patterns of Enterprise Application Architecture」において示した「Value Object」はこれとは意味が異なるData Access Object と組み合わせて、関係データベースからデータを検索するのに使うことも多い。

Data Transfer Object - Wikipedia

Data Transfer Object とビジネスオブジェクトや Data Access Object との違いは、DTO が自身のデータの格納と取り出し機能(アクセサメソッドとミューテータメソッド)しか持たない点である。

Data Transfer Object - Wikipedia

⇧ ってことらしい。

というか、「DTO(Data Transfer Object)」も「デザインパターン」の1種なんですと。

なんか、

のどっちのことについて言ってるのか、混乱を来すよね...

デザインパターン」のことをいう時は「DTO(Data Transfer Object)」って言うんでなくて、「DTO(Data Transfer Object)pattern」って言ってくれるとモヤモヤ感が無くなって良いんですがね...

用語の説明はもうちょっと厳密にしてくれないと、認識齟齬の雨あられになると思うんだけどな...

というか、「Data Access Object」も「Data Transfer Object」も「デザインパターン」って紹介してるのに、概要図みたいな情報はwikipediaで紹介してくれてないというね...

oreillyさんの説明によると、

www.oreilly.com

f:id:ts0818:20210724183150p:plain

⇧ 上図のような感じで、レイヤーをまたいで利用できるデータの入れ物を用意するってことが「Data Transfer Object」パターンらしい。

例えば、

blog.scottlogic.com

⇧ 上図のような感じで、フロント側からJSONなんかでデータから飛んできた場合を想定してると思うんだけど、DTO(Data Transfer Object)に変換することで、サーバー側で利用できる形にしたり、または、サーバー側でデータベースなんかからデータを引っ張て来た場合に、DTO(Data Transfer Object)に変換することで、サーバー側で利用できる形にするって感じなんかな。 

 

複数テーブルを考慮したDTO(Data Transfer Object)に対するDAO(Data Access Object)を作れば良いらしい

というわけで、Oracleさんが示してくれた例のように、 「複数テーブルを考慮したDTO(Data Transfer Object)」を作成して、その「DTO(Data Transfer Object)」を操作する「DAO(Data Access Object)」を作る感じになるみたいですね。

で、肝心の「複数テーブルを考慮したDTO(Data Transfer Object)」である「Page」クラスの実装(「オブジェクト」)を掲載してくれていないんですが、「aggregates」ってのは「集約」って意味らしく、おそらく「ドメイン駆動設計(DDD:Domain Driven Design)」の考え方でクラスの実装をすれば良いかと。

イメージ的には、

codezine.jp

 DDDにおける集約(Aggregates)とは、オブジェクトのまとまりを表し、整合性を保ちながらデータを更新する単位となります。通常はオブジェクトの集まりの「境界線」の意味で使われ、オブジェクト群の生成/読み込み/変更/保存といったライフサイクル管理が行われます。

実践DDD本 第10章「集約」~トランザクション整合性を保つ境界~ (1/3):CodeZine(コードジン)

⇧ 上記サイト様のイメージ図のような感じで、「オブジェクト」が「オブジェクト」を持つような構成ですかね。

DTO(Data Transfer Object)」については、メソッドとしては「アクセサ(getter、setter)」 だけを持つので、Oracleさんの例に出てきた「Page」クラスは、「Category」「Product」「Item」という「DTO(Data Transfer Object)」のクラスが存在する想定で、

class Page implements Serializable {

  private Category category;
  private Product product;
  private Item item;
  
  public Category getCategory() {
    return this.category;
  }
  
  public Product getProduct() {
    return this.product;
  }
  
  public Item getItem() {
    return this.item;
  }
  
  public void setCategory(Category category) {
    this.category = category;
  }
  
  public void setProduct(Product product) {
    this.product = product;
  }
  
  public void setItem(Item item) {
    this.item = item;
  }
}

⇧ みたいな「DTO(Data Transfer Object)」を用意する必要があるってことですかね?

Oracleさんの例だと、「category」っていうテーブルと「category_details」っていうテーブルをJOINしたテーブルから取得した結果の「ResultSet」クラスのオブジェクトから「Category」クラスのオブジェクトを作成してる感じなんかな。

おそらく、「category_details」テーブルに該当する「DTO(Data Transfer Object)」は、「Category」クラスの「DTO(Data Transfer Object)」に「集約」されてるってことなのかな?

複数テーブルをJOINしたテーブルから取得した結果を変換する「DTO(Data Transfer Object)」が無い場合は、

  • 新たに「DTO(Data Transfer Object)」を作成する
    • JOINした仮テーブルのDTOを作る
    • テーブルを追加してDTOを作る
  • 既存の「DTO(Data Transfer Object)」で済むようにする
    • SQLを見直す

のような対応をしていく感じになるのかな?

まぁ、でも、Oracleさんの例にあるように、「DTO(Data Transfer Object)」を「集約」した「DTO(Data Transfer Object)」を構成するのが一般的なんですかね?

なんか、こう、これだけ情報化社会になって来て情報が溢れてる気がするのに、実務で必要になってきそうな情報って滅多に見つからないよね...

というわけで、毎度のことながらモヤモヤ感が半端ない...

今回はこのへんで。