Cayenneを使った処理

重い処理を発行していると思われるReportSelectData.java内のgetSeletQueryメソッド内では、CayenneのExpressionというAipoとデータベースの橋渡しプログラムを使っていました。  いくつかメソッドが存在するのですが、getSeletQuery内で使われているメソッドは以下の四つでした。

出所 Cayenne:・http://www.docjar.com/docs/api/org/apache/cayenne/exp/ExpressionFactory.html

・http://www.atmarkit.co.jp/fjava/products/cayenne/cayenne_3.html

// valueをINの後に記述
public static Expression inDbExp(String pathSpec,
    Object values) {}

    A convenience shortcut for building IN DB expression. Return ASTFalse for empty collection.

// valueをLIKEの後に記述
public static Expression likeExp(String pathSpec,
    Object value) 

    A convenience shortcut for building LIKE expression.

// pathSpec = value を追加。
public static Expression matchExp(String pathSpec,
    Object value) 

    A convenience method to create an OBJ_PATH "equal to" expression.

// pathSpec != value を追加。
public static Expression noMatchExp(String pathSpec,
    Object value) 

    A convenience method to create an OBJ_PATH "not equal to" expression.

これらはすべてWHERE句の後に追加されます。

これらを理解したうえで、問題の重い処理について確認してみると、IN句の後に、たくさんのREPORT_IDが追加されるという原因の処理を行っているのは、349/381/414行目に記述されているfor文だということがわかります。 問題のfor文は以下の通りです。


List<EipTReportMap> queryList = q.fetchList(); List<Integer> resultid = new ArrayList<Integer>(); for (EipTReportMap item : queryList) { if (item.getReportId() != 0 && !resultid.contains(item.getReportId())) { resultid.add(item.getReportId()); } else if (!resultid.contains(item.getReportId())) { resultid.add(item.getReportId()); } } if (resultid.size() == 0) { // 検索結果がないことを示すために-1を代入 resultid.add(-1); } Expression ex = ExpressionFactory.inDbExp(EipTReport.REPORT_ID_PK_COLUMN, resultid); query.andQualifier(ex);

この処理から、REPORT_IDをresultidに格納して、それをinDbExpメソッドに渡していることがわかります。そのせいでIN句の後に沢山のREPORT_IDが追加されて、重い処理になっているのだと考えられます。 そこでSQL文に直して、for文以降の処理が必要であるかどうかについて考えたいと思います。 検索を担う部分をSQL文に直すと以下のようになると考えられます。

WHERE REPORT_NAME LIKE '%serch%' OR REPORT_NOTE LIKE '%serch%' (SELECT REPORT_ID IN ('resutid'...))

この場合、IN句に関わる処理は不必要であるように考えられます。 しかし実際にその処理を飛ばして見たところ、414行目のfor以外は、影響が現れました。 テーブルの結合がCayenne出来ないために、IN句にREPORT_IDを入れるという遠回りな処理を行っているのではないかと考えられます。