質問: **PlayFramework2.4とJavaでデータ検索をしたいです。** 現在はデータの検索はできているのですが、 ちょっとした条件の複雑さからコードが肥大化してしまいどうにかできないものかと悩んでおります。 なお、SQL文を直接埋め込むやり方も同じように複雑化してしまうのでEbeanのFindで検索したいです。 一つを例に挙げるのでアドバイスをいただきたいです。 地域を検索する際に **・都道府県で検索 ・特定の東京23区で検索 ・上記の東京23区以外の23区で検索 ・東京23区外で検索** としています。 そしてデータベースは**「都道府県」と「市区町村」**でカラムを分けています。 上記はセレクトボックスからの値を文字列として送られ来ます。 (例:東京都、渋谷区、その他23区、その他東京都etc) それぞれの条件分岐からの処理をコードで表すと ``` if(area.indexOf("区") != -1){ //”区”の文字が含まれているか否か if(area.equals("その他23区")){ 処理1 }else{ 処理2 } }else if(area.equals("その他東京都")){ 処理3 }else{ 処理4 } ``` としています。 それをEbeanを用いると ``` //都道府県で検索 .eq("prefectures", "都道府県名") //特定の23区 .eq("prefectures", "東京都") .eq("city", area) //その他23区 .eq("prefectures", "東京都") .ne("city" , "渋谷区").ne("city" , "新宿区")... //東京23区外 .eq("prefectures", "東京都") .not(Expr.ilike("city" , "%区%")) ``` としています。 それぞれ条件の指定の仕方が異なっており、処理を簡略化したいのです。 何卒、皆様のお知恵を拝借したい所存です。 宜しく御願い致します。
回答: 当回答ではコードの行数は減らないので > > コードが肥大化してしまいどうにかできないものか > > > というご質問の意図からは外れてしまうかも知れませんが、 Strategyパターン(だと思いますw)を使用すれば、検索条件の切り替えと個々の条件の指定を分離でき、見通しのよいコードにはなると思います。 まず、以下のように`ExpressionBuilder`インターフェースと、その内部クラスとして`Factory`クラスを定義します。 `ExpressionBuilder`インターフェースはStrategyパターンにおける"Strategy"で、`build`メソッドに渡された`ExpressionList`オブジェクトに検索条件をセットします。 `Factory`クラスの`getBuilder`メソッドは、引数で受け取った文字列を元に それぞれの検索条件に対応した`ExpressionBuilder`インターフェースの実装クラスを`return`します。 ``` public interface ExpressionBuilder { ExpressionList build(ExpressionList exp); public static class Factory { public static ExpressionBuilder getBuilder(String area) { if (area.indexOf("区") != -1) { // ”区”の文字が含まれているか否か if (area.equals("その他23区")) { // その他23区の検索条件を生成するクラス return new Other23kuExpressionBuilder(area); } else { // 特定の区(新宿区、渋谷区など)の検索条件を生成するクラス return new Specific23kuExpressionBuilder(area); } } else if (area.equals("その他東京都")) { // その他東京都の検索条件を生成するクラス return new Not23kuExpressionBuilder(area); } else { // 全国の検索条件を生成するクラス return new NationwideExpressionBuilder(area); } } } } ``` getBuilderメソッドから返却しているExpressionBuilderインターフェースの実装クラスは、 例えば以下のような感じになります。 ``` /** * 特定の区(新宿区、渋谷区など)の検索条件を生成するクラス */ class Specific23kuExpressionBuilder implements ExpressionBuilder { private final String area; Specific23kuExpressionBuilder(String area) { this.area = area; } @Override public ExpressionList build(ExpressionList exp) { return exp .eq("prefectures", "東京都") .eq("city", area); } } ``` ちなみに「その他23区」の検索条件は、 `.ne("city" , "渋谷区").ne("city" , "新宿区")...` より `.not(Expr.in("city", ...))` に、定数として定義した「特定の23区」を`in`メソッドの第二引数に渡すほうが私は可読性が向上するかと思いますが、いかがでしょうか? (EBeanは不勉強なので、同じ動作結果になるか自信はありませんが。。) ``` class Other23kuExpressionBuilder implements ExpressionBuilder { // 特定の23区 private static final String[] SPECIFIC_23KU = new String[] { "渋谷区", "新宿区", ... }; private final String area; Other23kuExpressionBuilder(String area) { this.area = area; } @Override public ExpressionList build(ExpressionList exp) { return exp .eq("prefectures", "東京都") .not(Expr.in("city", SPECIFIC_23KU)); } } ``` こうしておくと、実際に検索を実行する部分はたったこれだけの行数になります。 ``` ExpressionBuilder builder = ExpressionBuilder.Factory.getBuilder("豊島区"); ExpressionList> exp = ebeanServer.find(...).select(...).where(); builder.build(exp).findList(); ```