使用 ContentProvider 执行复杂原始查询的优雅方式

发布于 2024-10-09 15:37:29 字数 1647 浏览 3 评论 0原文

我使用 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 作为 hack 将 "user_id = " + Integer.toString(intUserId) 传递给该方法。

还有其他想法吗?

我应该注意的是,虽然我不想做任何黑客行为,但我已将我的 ContentProvider 设为私有,因为它仅供我的应用程序使用;所以如果我绝对需要的话,我可以。

I use a ContentProvider to speak with my application's database and I'm running into a bit of a problem.

I have a query that is slightly complicated. It looks something like this:

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);

Selection is:

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

My problem is my sub-queries. I have a constraint I need to add, but no good way of getting that constraint down the pipe to the method. I need to use the correct user_id on the sub-queries.

At this point, I think I have 2 options:

1) Parse out the user_id substring from selection.

2) Use selectionArgs as a hack to pass "user_id = " + Integer.toString(intUserId) to the method.

Any other ideas?

I should note that while I'd rather not doing anything hack-ish, I have made my ContentProvider private as it is intended to only be used by my application; so if I absolutely have to, I can.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

中二柚 2024-10-16 15:37:29

当处理这样的复杂查询时,构建器类可以派上用场。
它避免了您将它们转换为字符串,希望这对您有帮助。

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();

}

when dealing with complex queries like this, a builder class can come handy.
It avoids you having to convert them to String, hope this helps you.

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;
}

}

Usage is like below

{

    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();

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文