web-dev-qa-db-ja.com

パラメータとしてのMyBatis文字列

MyBatisのSelectステートメントにStringパラメーターを使用したい。私のmapper.xml:

<select id="selectAll" parameterType="String" resultMap="fastXMLResultMap">
        SELECT CREATIONDATE, DOCUMENTID, TITEL, REGTITEL, INFORCEDATE, DOCTYPE
        FROM #{databBaseTable}
</select>

そして、呼び出し関数:

public List<FastXMLObject> selectAll(String databBaseTable) {

    SqlSession session = sqlSessionFactory.openSession();

    System.out.println("Table: "+databBaseTable);

    try {
        List<FastXMLObject> list = session.selectList("FastXMLObject.selectAll",databBaseTable);
        return list;
    } finally {
        session.close();
    }
}

文字列dataBaseTableは、さまざまなテーブルから動的にデータを取得したいので、データベースのテーブルの名前です(誰がそう思ったでしょう)。

ただし、残念ながら、これは機能しません。エラー:ORA-00903:UngültigerTabellenname(無効なテーブル名)ですが、機能しません。 「databBaseTable」の値を出力すると、それはテーブルの正確な名前です。そして、テーブルの名前を変数なしでmapper.xmlに書き込むと、機能します。私は何を間違えますか?

8
Metalhead89

'#'の代わりに_${dataBaseTable}_を使用します。違いは、 '#'がPreparedStatementの置換に使用されることです。 「$」は直接文字列置換用です。

ただし、これを行うと、テーブル名をパラメータとしてselectList()呼び出しに渡すことができなくなります。テーブル名をプロパティとして設定する必要があります。プロパティは、MyBatis config.xmlの_<properties>_要素を使用して設定するか、Configuration.getVariables()を使用してコードで直接設定できます。

MyBatis Docs の「StringSubstitution」セクションを参照してください。

25
AngerClown

わかりました。なぜこれが機能するのかはわかりませんが、問題を解決するために以下を使用しました。

<select id="selectAll" parameterType="String" resultMap="fastXMLResultMap">
        SELECT CREATIONDATE, DOCUMENTID, TITEL, REGTITEL, INFORCEDATE, DOCTYPE
        FROM ${value}
</select>

プロパティなどは設定していません。FROM #{databBaseTable}からFROM ${value}に変更しただけです。

私は誰かがこれがうまくいく理由を答えることができました。しかし今のところ、これは本当に私を助けました。

7
Metalhead89

#{..}構文では、MyBatisはjdbc PreparedStatementオブジェクトを使用しますが、このオブジェクトではテーブル名をパラメーターとして指定できません。 #{..}を使用すると、sqlステートメントのパラメーターのみをパラメーター化できます。

$ {..}構文を使用すると、MyBatisは単純な古い文字列置換を行うため、必要なSQLのほとんどすべての部分を自由にパラメーター化できます。

注:ちなみに、#{..}を使用すると、SQLインジェクションからかなり安全になりますが、$ {..}を使用すると、このような攻撃への扉が開かれます。

4
johnm