Элегантный способ выполнения сложных необработанных запросов с использованием ContentProvider - PullRequest
7 голосов
/ 28 декабря 2010

Я использую ContentProvider для общения с базой данных моего приложения, и у меня возникла небольшая проблема.

У меня есть запрос, который немного сложен.Это выглядит примерно так:

String sql =
    "select " +
    "  tblHistory._id _id, " +
    "  tblHistory.item item, " +
    "  tblHistory.updated_on updated_on, " +
    "  (select _id from tblList " +
        "where tblList.item = tblHistory.item) list_id, " +
    "  1 priority, " +
    "from " +
    "  tblHistory " +
    "where " +
    "  tblHistory.status <> 'STATE_DELETING' and " + selection + " " +
    "union " +
    "select " +
    "  tblSearch._id _id, " +
    "  tblSearch.item item, " +
    "  -1 updated_on, " +
    "  (select _id from tblList " +
        "where tblList.item = tblSearch.product_name) list_id, " +
    "  2 priority, " +
    "from " +
    "  tblSearch " +
    "where " +
    "  not exists (select * from tblHistory " +
        "where tblHistory.item = tblSearch.product_name) " +
    "order by " +
    "  priority, _id asc";

    c = mDb.rawQuery(sql, null);

Выбор:

String where = "tblHistory.user_id="
               + Integer.toString(intUserId)
               + " and tblHistory.item like '%"
               + strSearch + "%'";

Моя проблема - мои подзапросы.У меня есть ограничение, которое нужно добавить, но нет хорошего способа получить это ограничение по трубе к методу.Мне нужно использовать правильный user_id для подзапросов.

На данный момент, я думаю, у меня есть 2 варианта:

1) Анализировать подстроку user_id из выбора.

2) Используйте selectionArgs как хак, чтобы передать "user_id = " + Integer.toString(intUserId) методу.

Любые другие идеи?

Я должен отметить, что хотя я бы предпочел ничего не делатьхак, я сделал свой ContentProvider приватным, так как он предназначен только для моего приложения;так что, если мне абсолютно необходимо, я могу.

1 Ответ

2 голосов
/ 17 января 2014

при работе со сложными запросами, подобными этому, может пригодиться класс строителя. Это избавляет вас от необходимости конвертировать их в строку, надеюсь, это поможет вам.

public class SqlQueryBuilder {

private static final String SELECT = "SELECT";

private static final String COMA = " , ";

private static final String WHERE = " where ";

private static final String EQUALS = " = ";

private static final String NOT_EQUALS = " != ";

private static final String FROM = " FROM ";

private final StringBuilder mStrBuilder = new StringBuilder();

public void init() {
    mStrBuilder.setLength(0);
}

public SqlQueryBuilder select(Object ...columns) {
    mStrBuilder.append(SELECT);
    for(Object column:columns) {
        mStrBuilder.append(column);
        mStrBuilder.append(COMA);
    }
    return this;
}

public SqlQueryBuilder where(Object conditionVar) {
    mStrBuilder.append(WHERE);
    mStrBuilder.append(conditionVar);
    return this;
}


public SqlQueryBuilder equalsVal(Object equalsVal) {
    mStrBuilder.append(EQUALS);
    mStrBuilder.append(equalsVal);
    return this;
}

public SqlQueryBuilder notEqualsVal(Object notEqualsVal) {
    mStrBuilder.append(NOT_EQUALS);
    mStrBuilder.append(notEqualsVal);
    return this;
}

public SqlQueryBuilder from(Object from) {
    mStrBuilder.append(FROM);
    mStrBuilder.append(from);
    return this;
}

public String build() {
    final String sqlQuery = mStrBuilder.toString(); 
    init();
    return sqlQuery;
}

}

Использование как ниже

{

    SqlQueryBuilder sqlQueryBuilder = new SqlQueryBuilder();

    String innerQuery = sqlQueryBuilder.select("_id").from("tblList")
            .where("tblList.item").equalsVal("tblHistory.item").build();

    String query = sqlQueryBuilder.select("tblHistory._id _id",
            "tblHistory.item", "tblHistory.updated_on updated_on",
            innerQuery + " list_id", "1 priority").build();

}
...