[Seasar-user:14866] [S2Dao]N:0..1マッピングについて

Yutaka Nishino [E-MAIL ADDRESS DELETED]
2008年 6月 30日 (月) 15:32:19 JST


お世話になっております。
西野と申します。

S2DaoのN:1マッピングについて質問させて頂きます。

(質問)
S2DaoでN:1マッピングを用いて関連する1側のデータを取得しようと考えています。
S2DaoではN:1の1側が存在しないようなケース(N:0..1)はサポートしていますでしょうか?
このケースを実際に試してみたところ、N側のデータをListで取得した場合と、
1件のみ取得した場合で1側のデータが存在しない場合の挙動が異なっている為、
質問させて頂きました。
できましたら、1件取得の場合も1側のインスタンスが生成されないようにして頂けないでしょうか?

(環境)
S2Container: 2.3.23
S2Dao: 1.0.47(1.0.48を用いて同一の現象が発生している事を確認しています。)
DB: Oracle 10.2.0.1.0
  HSQLDB server 1.7.3※(左記のDBを用いて現象の再現は出来ています。)


(検証内容)
S2Dao1.0.47と1.0.48両方で以下の検証を行い、同じ結果となりました。
1.s2-dao-examplesのソースコードの修正。
s2dao/s2-dao-examples/src/main/java/examples/dao/Employee.java
のサンプルの上記のソースコードで、
N:1マッピングのキーにnull設定できるよう修正。
private int deptno;
を以下のように修正し、アクセッサもそれに合わせて修正しました。
private Integer deptno;

2.テストの実行
/s2dao-sample/src/test/java/examples/dao/Employee2DaoClientTest.java
を実行した場合、期待通りの結果が返ってきます。
・Listでの取得(List getEmployees(String ename))結果のtoStringの内容
7788, SCOTT, ANALYST, 7566, 1982-12-09 00:00:00.0, 3000.0, null, 20, 2005-01-18 13:09:32.213 {20, RESEARCH, DALLAS, 0}
・1件取得(public Employee getEmployee(int empno))結果のtoStringの内容
7788, SCOTT, ANALYST, 7566, 1982-12-09 00:00:00.0, 3000.0, null, 20, 2005-01-18 13:09:32.213 {20, RESEARCH, DALLAS, 0}

3.N:1マッピングで1側のデータが無かった場合のテスト
HSQL Database Managerで接続し、以下のSQLを発行しcommitします。
(2の検証でヒットしていたデータを書き換え1側が存在しないように書き換え。)
update emp set
deptno=null
where empno=7788;
その後、
/s2dao-sample/src/test/java/examples/dao/Employee2DaoClientTest.java
を実行した場合、Listで取得した場合と結果が異なってきます。
・Listでの取得(List getEmployees(String ename))結果のtoStringの内容
7788, SCOTT, ANALYST, 7566, 1982-12-09 00:00:00.0, 3000.0, null, null, 2005-01-18 13:09:32.213 {null}
・1件取得(public Employee getEmployee(int empno))結果のtoStringの内容
7788, SCOTT, ANALYST, 7566, 1982-12-09 00:00:00.0, 3000.0, null, null, 2005-01-18 13:09:32.213 {0, null, null, 0}
リストで取得した場合、N:1のマッピングのキーがnullの場合、関連する1側に値が設定されていないインスタンスが
セットされてしまいます。

4.ソースを確認したところ、BeanListMetaDataResultSetHandlerとBeanMetaDataResultSetHandleで
 1側の関連するデータのインスタンスを生成する部分の実装が異なります。
org.seasar.dao.impl.BeanListMetaDataResultSetHandler#handle(ResultSet rs)では
以下のようになっています。
createRelationKey()を呼び出して、そのrelKeyがnullであればインスタンスが生成されない
ような実装になっています。
======BeanListMetaDataResultSetHandlerソース抜粋====================================
                RelationPropertyType rpt = getBeanMetaData()
                        .getRelationPropertyType(i);
                if (rpt == null) {
                    continue;
                }
                Object relationRow = null;
                Map relKeyValues = new HashMap();
                // TODO 1レコード目でnullが返るなら、2レコード目以降は不要では?
                RelationKey relKey = createRelationKey(rs, rpt, columnNames,
                        relKeyValues);
                if (relKey != null) {
                    relationRow = relRowCache.getRelationRow(i, relKey);
                    if (relationRow == null) {
                        relationRow = createRelationRow(rs, rpt, columnNames,
                                relKeyValues, relationPropertyCache);
                        relRowCache.addRelationRow(i, relKey, relationRow);
                    }
                }	
==========================================

org.seasar.dao.impl.BeanMetaDataResultSetHandle#handle(ResultSet resultSet)では
実装が異なり、N:1のマッピングキーがnullの場合でもcreateRelationRowが呼び出され、インスタンスが
生成されています。
======BeanMetaDataResultSetHandleソース抜粋====================================
                RelationPropertyType rpt = getBeanMetaData()
                        .getRelationPropertyType(i);
                if (rpt == null) {
                    continue;
                }
                Object relationRow = createRelationRow(resultSet, rpt,
                        columnNames, null, relationPropertyCache);
==========================================


よろしくお願い致します。


Seasar-user メーリングリストの案内