EzJDBCで結合した時の自動バインディングの秘密

EzJDBCの自動バインディングの方法は前回の「EzJDBCの自動バインディングの秘密」で説明いたしました。

今回は、テーブルをJOINした結果をエンティティにマッピングする場合の自動バインディングについて説明します。以下の関係のテーブルを結合した結果を例に説明いたします。

 【利用テーブル】
  1.CUSTOMERテーブル    プライマリーキー:ID
  2.ORDERテーブル       プライマリーキー:NO
  3.ORDER_ITEMテーブル  プライマリーキー:ORDER_NO, SEQ
  4.ADDRESSテーブル      プライマリーキー:ZIP_CODE

 【テーブル関係】
  CUSTOMER : ORDER : ORDER_ITEM = 1 : n : m
  CUSTOMER : ADDRESS            = 1 : 1

EzJDBCでテーブルを結合した照会結果をEntityにマッピングするコードは下記のようになります。

1.EzJDBC#relationメソッドを利用しない場合

CUSTOMER CUS = new CUSTOMER();
List list = EzJDBC.froms(CUS).join(CS.ODR.ODI).join(CUS.ADR)
                  .where(CUS.name.like("Taka%")).find(Customer.class);

この時バイトコードエンハンスメントで作成されるバインド用ソースは以下の様になります。

public static List getCustomerList(ResultSet resultSet) {
 List list = new ArrayList();
 while(resultSet.next()) {
   // Customerエンティティーを生成します
   Customer customer = new Customer();
   customer.id = resultSet.getInt(1);
   customer.name = resultSet.getString(2);
   customer.age = resultSet.getInt(3);
   ...
   // Customerエンティティを結果Listに追加します
   list.add(customer);

   // Orderエンティティーを生成します
   Order order = new Order();
   order.no = resultSet.getString(11);
   order.orderDate = resultSet.getDate(12);
   order.amount = resultSet.getInt(13);
   ...
   // OrderエンティティをCustomerエンティティのorderListに追加します
   customer.orderList.add(order);
   // OrderItemエンティティーを生成します
   OrderItem orderItem = new OrderItem();
   orderItem.orderNo = resultSet.getString(21);
   orderItem.seq = resultSet.getInt(22);
   order.itemName = resultSet.getInt(23);
   ...
   // OrderItemエンティティをOrderエンティティのorderItemListに追加します
   order.orderItemList.add(orderItem);

   // Addressエンティティーを生成します
   Address address = new Address();
   address.zipCode = resultSet.getString(31);
   ...
   // AddressエンティティをCustomerエンティティのaddressにセットします
   customer.address = address;
 }
 return list;
}

上記コードは、照会結果の1レコード毎にCustomerエンティティを生成しマッピングしていきます。
つまり「照会結果のレコード数=Customerエンティティ数」となるため、重複したCustomerエンティティが結果Listに入っています。
where(CUS.name.like("Taka%"))の条件にあうCUSTOMERテーブルのデータが1レコードだとしても、
子テーブルであるORDERが1レコード、孫テーブルであるORDER_ITEMが5レコードあった場合は結果リストList
のサイズは5になるわけです。


次にEzJDBC#relationメソッドを利用した場合の結果を見てみましょう。

2.EzJDBC#relationメソッドを利用した場合

 CUSTOMER CUS = new CUSTOMER();
 List list = EzJDBC.froms(CUS).join(CS.ODR.ODI).join(CUS.ADR)
              .where(CUS.name.like("Taka%")).relation().find(Customer.class);

この時バイトコードエンハンスメントで作成されるバインド用ソースは以下の様になります。

public static List getCustomerList(ResultSet resultSet) {
 // エンティティーの初期設定
 Customer customer = null;
 Order order = null;
 OrderItem orderItem = null;
 Address address = null;

 // Customerエンティティーリスト
 List list = new ArrayList();
 while(resultSet.next()) {
   // Customerテーブルのキーブレイクチェック
   if(customer == null || customer.id != resultSet.getInt(1)) {
     // Customerエンティティーを生成します
     customer = new Customer();
     customer.id = resultSet.getInt(1);
     customer.name = resultSet.getString(2);
     customer.age = resultSet.getInt(3);
     ...
     // Customerエンティティを結果Listに追加します
     list.add(customer);
     // 子・孫エンティティを初期化します
     order = null;
     orderItem = null;
     address = null;
   }

   // Orderテーブルのキーブレイクチェック
   if(order == null || !order.no.equals(resultSet.getString(11))) {
     // Orderエンティティーを生成します
     order = new Order();
     order.no = resultSet.getString(11);
     order.orderDate = resultSet.getDate(12);
     order.amount = resultSet.getInt(13);
     ...
     // OrderエンティティをCustomerエンティティのorderListに追加します
     customer.orderList.add(order);
     // OrderItemエンティティにnullをセット
     orderItem = null;
   }

   // OrdeItemrテーブルのキーブレイクチェック
   if(orderItem == null || !orderItem.orderNo.eqauls(resultSet.getString(21)) ||
     // OrderItemエンティティーを生成します
     orderItem = new OrderItem();
     orderItem.orderNo = resultSet.getString(21);
     orderItem.seq = resultSet.getInt(22);
     order.itemName = resultSet.getInt(23);
     ...
     // OrderItemエンティティをOrderエンティティのorderItemListに追加します
     order.orderItemList.add(orderItem);
   }

   // Addressテーブルのキーブレイクチェック
   if(address == null || !address.zipCode.equals(resultSet.getString(31))) {
     // Addressエンティティーを生成します
     Address address = new Address();
     address.zipCode = resultSet.getString(31);
     ...
     // AddressエンティティをCustomerエンティティのaddressにセットします
     customer.address = address;
   }
 }
 return list;
}

上記コードは、照会結果をCUSTOMERテーブルのキーで集約し、キーが変わった時のみCustomerエンティティを生成しマッピングしていきます。
つまり「照会結果のレコード数!=Customerエンティティ数」となります。
where(CUS.name.like("Taka%"))の条件にあうCUSTOMERテーブルのデータが1レコードだとして、
子テーブルであるORDERが1レコード、孫テーブルであるORDER_ITEMが5レコードあったとしても、結果リストListのサイズは1になります。


つまりEzJDBC#relationの場合は結合(JOIN)した結果データをオブジェクトツリーとしてマッピングしてくれる機能は、こうやって実装されているのですね^^