潜伏バグからのロングフリーズ

Javaっぽいエンジニアの徒然草

Javaで定数定義したSQLを動的に変更する(=ただの置換) からの final修飾子のおさらい

JavaのStringでSQLを定義。

条件に応じて参照テーブルを変更する。

 ex) xxFlagがONの時はTABLE_1, OFFの時はTABLE_2を参照したい。

   それ以外の結合や絞込み条件などは全く一致する前提。

 

--------------------------------------------------------------------------------------

 

SQLを2つ書く方法】

何の捻りもなく、そのまんま。

 

private static final String SQL_SEARCH_1 =

"SELECT "

    + TABLE_1 + "." + field1 + ", "

    + TABLE_1 + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_1

+ " WHERE "

    + 略

;

 

private static final String SQL_SEARCH_2 =

"SELECT "

    + TABLE_2 + "." + field1 + ", "

    + TABLE_2 + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_2

+ " WHERE "

    + 略

 

;

 

メリット

・参照テーブル毎に(結合、絞込みなどの)条件を変えたい、といった変更に強い。

 

デメリット

・2重メンテが発生

・コードが冗長

 

--------------------------------------------------------------------------------------

 

【置換する方法】

 

// 置換用文字列

private static final String TABLE_X = "@TABLE_X@";

 

private static final String SQL_SEARCH =

"SELECT "

    + TABLE_X + "." + field1 + ", "

    + TABLE_X + "." + field2 + ", "

    + ・

    + ・

    + ・

+ " FROM "

    + TABLE_X

+ " WHERE "

    + 略

 

;

 

--------------------------

 

String sql = xxFlag ? SQL_SEARCH.replaceAll(TABLE_X , TABLE_1)

                                 : SQL_SEARCH.replaceAll(TABLE_X , TABLE_2);

 

Point

・置換用文字列は@で囲む等、普通は使用しない形で記載する(誤置換防止)。

 →例えば置換用文字列を「S」と定義すると、SELECTの「S」が置換されてしまう。

 

メリット

・コードが簡潔に書ける

 

デメリット

・参照テーブル毎に(結合、絞込みなどの)条件を変えたい、といった変更に弱い。

 

 

ちなみに、

 SQL_SEARCH はstatic finalだけど、replaceAllで変更できるの?

 ▶︎ 変更ではなく、新規Stringインスタンスが返るので問題なし!

 

 

一応JavaDocも確認。

 JavaDocのStringクラス

 ※1.5版から引用。古いけど多分変わってないはず。

java.lang.String

 public final class String

 extends Object

 implements Serializable, Comparable<String>, CharSequence

 

文字列は定数です。この値を作成したあとに変更はできません。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

特に意識していなかったけれど、Stringクラスはfinalだったらしい。

 

■final修飾子メモ

 final クラス: サブクラスの作成ができなくなる

 final メソッド: オーバーライドができなくなる

 final 基本型変数: 変数の値の変更ができなくなる

 final 参照型変数: 変数の参照の変更ができなくなる

   ※setter/getterなどで、インスタンスの値変更はできる点に注意

   下記ケースはエラーにならずに正常に書き換えられる。

 

 

 

 

public class XxxBean {

 

    private String str;

    privateintnum;

 

    // constructor

    public XxxBean(String str, int num) {

        this.str = str;

        this.num = num;

    }

 

    // getter and setter

    public String getStr() {

        returnstr;

    }

    public void setStr(String str) {

        this.str = str;

    }

    public int getNum() {

        returnnum;

    }

    public void setNum(int num) {

        this.num = num;

    }

 

}

 

 

 

publicclass Test {

 

    public static void main(String [] args) {

        final XxxBean bean = new XxxBean("aaa", 1);

        bean.setStr("bbb");

        bean.setNum(2);

 

        System.out.println(bean.getStr());

        System.out.println(bean.getNum());

    }

 

}

 

 

仮に、

 bean = null;

と書いた場合はコンパイルエラーになる。