1

遊びに!2.x アプリケーションで、ebean を使用して MySQL サーバーに簡単なクエリを送信しようとしています。

私の完全なクラスは次のようになります。

public static List<Venue> search(String query) {
    List<Venue> matches = new ArrayList<Venue>();
    try {
        String q = query.replace(" ", "");

        String sql =    "SELECT  v.id, c.company, c.postcode \n" +
                        "FROM    venue v \n" +
                        "JOIN    contact c ON (c.id = v.id) \n" +
                        "WHERE   REPLACE(c.postcode, ' ', '') LIKE '%" + q + "%' \n" +
                        "    OR  c.company LIKE '%" + q + "%'";

        RawSql rawSql = RawSqlBuilder.unparsed(sql)
            .columnMapping("v.id", "id")
            .columnMapping("c.company", "contact.company")
            .columnMapping("c.postcode", "contact.postcode")
            .create();

        Query<Venue> eQ = Ebean.find(Venue.class);

        eQ.setRawSql(rawSql);

        matches = eQ.findList();
    }
    catch (Exception e) {
        Utils.eHandler("Venue.search(" + query + ")", e);
    }
    finally {
        return matches;
    }
}

ただし、行を実行すると...

matches = eQ.findList();

..MySQL エラー (?) のように見える次のエラーが発生します。

Query threw SQLException:Column Index out of range, 0 < 1.
Bind values:[]
Query was:
SELECT  v.id, c.company, c.postcode
FROM    venue v
JOIN    contact c ON (c.id = v.id)
WHERE   REPLACE(c.postcode, ' ', '') LIKE '%sw3%'
        OR  c.company LIKE '%sw3%'

クエリ自体は問題ありません。たとえば、エラー メッセージからバージョンをコピーして MySQL Workbench に貼り付けることができ、問題なく実行できます。

2つ以上の「OR」句が必要になるため、RawSqlを使用していることに注意してください。私が知る限り、これがそれを行う唯一の方法です。

誰でも助けることができますか?

ありがとう!

4

1 に答える 1

2

問題 (または少なくとも解決策) を見つけました。「Contact」は「Venue」の子オブジェクトであるため、Contact 識別子を指定せずに Contact フィールド (「contact.company」など) にマップすることはできません。そのため、contact.id に適切な要素を追加した次のコードは機能します。

String sql =    "SELECT  v.id, c.id, c.company, c.postcode " +
                "FROM    venue v " +
                "JOIN    contact c ON (c.id = v.id) " +
                "WHERE   REPLACE(c.postcode, ' ', '') LIKE '%" + q + "%' " +
                "    OR  c.company LIKE '%" + q + "%'";

RawSql rawSql = RawSqlBuilder.unparsed(sql)
    .columnMapping("v.id", "id")
    .columnMapping("c.id", "contact.id")
    .columnMapping("c.company", "contact.company")
    .columnMapping("c.postcode", "contact.postcode")
    .create();

さらに良いことに、ルーチンはクエリで一致する「会場」オブジェクトのリストを返すだけなので、追加のフィールドを含める必要さえないので、本当に必要なのは次のことだけでした (これも機能します)。

String sql =    "SELECT  v.id " +
                "FROM    venue v " +
                "JOIN    contact c ON (c.id = v.id) " +
                "WHERE   REPLACE(c.postcode, ' ', '') LIKE '%" + q + "%' " +
                "    OR  c.company LIKE '%" + q + "%'";

RawSql rawSql = RawSqlBuilder.unparsed(sql)
    .columnMapping("v.id", "id")
    .create();
于 2012-12-21T14:10:47.333 に答える