将 SQL 查询分成多个部分以访问内容提供程序
Break SQL query into parts for accessing content provider
我有一个来自字符串的 SQL 查询并试图访问 ContentProvider
。 sql 查询如下所示:
String query = "SELECT * FROM application_settings WHERE _id = ?";
我必须通过 ContentResolver
来访问内容提供者:
context.getContentResolver().query()
但查询方法接受:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
有什么方法可以将字符串查询拆分为投影、选择、selectionArgs 和 sortOrder?
我不想执行原始查询,所以我更希望有一个带有绑定值的函数解决方案。
我刚刚编写了一个库来提供您所需要的。您只需要将其复制并粘贴到项目中,如果您想添加、扩展和自定义它,则可以根据您的要求进行。
SqliteHandler.java
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
class SqliteHandler {
// VERY IMPORTANT MAKE SURE IT'S CORRECT AND REGISTERED IN THE MANIFEST
private String PROVIDER_NAME = "com.example.android.mySqlite";
private String CONTENT_URL = "content://" + PROVIDER_NAME + "/";
private Context context;
SqliteHandler(Context context, String PROVIDER_NAME) {
this.context = context;
this.PROVIDER_NAME = PROVIDER_NAME;
}
Cursor exeQuery(String query) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String selection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] projection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(queryObject obj) {
try {
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
class queryObject {
Uri uri;
String[] projection;
String selection;
String[] selectionArgs;
String sortOrder;
queryObject(String table_name, String[] projection, String selection, String[]
selectionArgs) {
this.uri = Uri.parse(CONTENT_URL + table_name);
this.projection = projection;
this.selection = selection;
this.selectionArgs = selectionArgs;
}
}
queryObject convertQueryStringToQueryObject(String query) {
try {
String selection = null;
String[] selectionArgs = null;
query = query.toLowerCase();
String[] s = query.split("select")[1].split("from");
String[] projection = s[0].split(",");
String[] s2 = s[1].split("where");
String table_name = s2[0];
String logText = "";
if (s2.length > 1) {
selection = s2[1];
String[] args = s2[1].split("=");
selectionArgs = new String[args.length - 1];// half of the args are values others are keys
int count = 0;
for (int i = 1; i < args.length; i++) {
selectionArgs[count] = args[i]
.split("and")[0]
.split("or")[0]
.replace(" ", "")
.replace("and", "")
.replace("or", "");
count++;
}
for (int i = 0; i < selectionArgs.length; i++) {
logText += selectionArgs[i];
if (i < selectionArgs.length - 1) logText += ",";
selection = selection.replace(selectionArgs[i], "?");
}
}
Log.i("table_name", table_name);
Log.i("selection: ", selection == null ? "null" : selection);
Log.i("selectionArgs", logText.equals("") ? "null" : logText);
logText = "";
for (int i = 0; i < projection.length; i++) {
logText += projection[i];
if (i < projection.length - 1) logText += ",";
}
Log.i("projection", logText);
return new queryObject(table_name, projection, selection, selectionArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}}
如何使用
实例化SqliteHandler
,传递有效PROVIDER_NAME
并确保你的CONTENT_PROVIDER
在AndroidManiFest.xml
中注册是非常重要的。为了说明它是如何工作的,我们传递三个不同的查询并获得 return 值,这些值是 queryObject
类型的对象
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
方法convertQueryStringToQueryObject
将query string
转换成query class
,然后我们就可以用这个class为getContentResolver().query()
。
重要提示:因为getContentResolver().query()
需要Uri
。因此,我们需要从table_name
创建一个Uri
。因此,我们需要将有效的 PROVIDER_NAME
传递给 SqliteHandler
.
的实例
输出日志
如您所见,三个不同的查询分解为我们可以在 getContentResolver().query()
中使用的参数
// 1th query
I/table_name: table_name
I/selection:: null
I/selectionArgs: null
I/projection: *
// 2th query
I/table_name: table_name
I/selection:: _id = ?
I/selectionArgs: ?
I/projection: *
// 3th query
I/table_name: table_name
I/selection:: param1 =? and param2=? or param3=?
I/selectionArgs: "a","b","c"
I/projection: param1,param2,param3
完整示例
在 SqliteHandler.java
中有一个 exeQuery
方法,它有几个重载。此外,根据不同的输入参数,您可以在Content Provider
处有一个Cursor
。
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery(obj1);
Cursor c = sh.exeQuery(obj2);
Cursor c = sh.exeQuery(obj3);
Cursor c = sh.exeQuery("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery("SELECT * FROM table_name WHERE _id = ?",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT * FROM table_name"," _id = ? ",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT ? FROM table_name WHERE _id = ?",new String[]{"Field"},new String[]{"whereArg"});
但是,如果您不想使用 exeQuery
,请尝试以下步骤:
queryObject obj = convertQueryStringToQueryObject(query);
Cursor c = this.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
来自 android 文档 https://developer.android.com/guide/topics/providers/content-provider-basics#ClientProvider
cursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
projection, // The columns to return for each row
selectionClause, // Selection criteria
selectionArgs, // Selection criteria
sortOrder); // The sort order for the returned rows
你可以做到
String[] projection = {"*"};
String[] selectionArgs = {"1", "2"}; //your ids here
Cursor cursor = getContentResolver().query(Uri.parse("content://your_provider/your_table"), projection, "_id", selectionArgs, null);
cursor.close();
要创建提供商,请参阅此 https://developer.android.com/guide/topics/providers/content-provider-creating#top_of_page
也看到这个答案
我有一个来自字符串的 SQL 查询并试图访问 ContentProvider
。 sql 查询如下所示:
String query = "SELECT * FROM application_settings WHERE _id = ?";
我必须通过 ContentResolver
来访问内容提供者:
context.getContentResolver().query()
但查询方法接受:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
有什么方法可以将字符串查询拆分为投影、选择、selectionArgs 和 sortOrder?
我不想执行原始查询,所以我更希望有一个带有绑定值的函数解决方案。
我刚刚编写了一个库来提供您所需要的。您只需要将其复制并粘贴到项目中,如果您想添加、扩展和自定义它,则可以根据您的要求进行。
SqliteHandler.java
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
class SqliteHandler {
// VERY IMPORTANT MAKE SURE IT'S CORRECT AND REGISTERED IN THE MANIFEST
private String PROVIDER_NAME = "com.example.android.mySqlite";
private String CONTENT_URL = "content://" + PROVIDER_NAME + "/";
private Context context;
SqliteHandler(Context context, String PROVIDER_NAME) {
this.context = context;
this.PROVIDER_NAME = PROVIDER_NAME;
}
Cursor exeQuery(String query) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String selection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, obj.projection, selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(String query, String[] projection, String[] selectionArgs) {
try {
queryObject obj = convertQueryStringToQueryObject(query);
return context.getContentResolver().query(obj.uri, projection, obj.selection, selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Cursor exeQuery(queryObject obj) {
try {
return context.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
class queryObject {
Uri uri;
String[] projection;
String selection;
String[] selectionArgs;
String sortOrder;
queryObject(String table_name, String[] projection, String selection, String[]
selectionArgs) {
this.uri = Uri.parse(CONTENT_URL + table_name);
this.projection = projection;
this.selection = selection;
this.selectionArgs = selectionArgs;
}
}
queryObject convertQueryStringToQueryObject(String query) {
try {
String selection = null;
String[] selectionArgs = null;
query = query.toLowerCase();
String[] s = query.split("select")[1].split("from");
String[] projection = s[0].split(",");
String[] s2 = s[1].split("where");
String table_name = s2[0];
String logText = "";
if (s2.length > 1) {
selection = s2[1];
String[] args = s2[1].split("=");
selectionArgs = new String[args.length - 1];// half of the args are values others are keys
int count = 0;
for (int i = 1; i < args.length; i++) {
selectionArgs[count] = args[i]
.split("and")[0]
.split("or")[0]
.replace(" ", "")
.replace("and", "")
.replace("or", "");
count++;
}
for (int i = 0; i < selectionArgs.length; i++) {
logText += selectionArgs[i];
if (i < selectionArgs.length - 1) logText += ",";
selection = selection.replace(selectionArgs[i], "?");
}
}
Log.i("table_name", table_name);
Log.i("selection: ", selection == null ? "null" : selection);
Log.i("selectionArgs", logText.equals("") ? "null" : logText);
logText = "";
for (int i = 0; i < projection.length; i++) {
logText += projection[i];
if (i < projection.length - 1) logText += ",";
}
Log.i("projection", logText);
return new queryObject(table_name, projection, selection, selectionArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}}
如何使用
实例化SqliteHandler
,传递有效PROVIDER_NAME
并确保你的CONTENT_PROVIDER
在AndroidManiFest.xml
中注册是非常重要的。为了说明它是如何工作的,我们传递三个不同的查询并获得 return 值,这些值是 queryObject
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
方法convertQueryStringToQueryObject
将query string
转换成query class
,然后我们就可以用这个class为getContentResolver().query()
。
重要提示:因为getContentResolver().query()
需要Uri
。因此,我们需要从table_name
创建一个Uri
。因此,我们需要将有效的 PROVIDER_NAME
传递给 SqliteHandler
.
输出日志
如您所见,三个不同的查询分解为我们可以在 getContentResolver().query()
// 1th query
I/table_name: table_name
I/selection:: null
I/selectionArgs: null
I/projection: *
// 2th query
I/table_name: table_name
I/selection:: _id = ?
I/selectionArgs: ?
I/projection: *
// 3th query
I/table_name: table_name
I/selection:: param1 =? and param2=? or param3=?
I/selectionArgs: "a","b","c"
I/projection: param1,param2,param3
完整示例
在 SqliteHandler.java
中有一个 exeQuery
方法,它有几个重载。此外,根据不同的输入参数,您可以在Content Provider
处有一个Cursor
。
SqliteHandler sh = new SqliteHandler(this,"PROVIDER_NAME");
SqliteHandler.queryObject obj1 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name");
SqliteHandler.queryObject obj2 = sh.convertQueryStringToQueryObject("SELECT * FROM table_name WHERE _id = ?");
SqliteHandler.queryObject obj3 = sh.convertQueryStringToQueryObject("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery(obj1);
Cursor c = sh.exeQuery(obj2);
Cursor c = sh.exeQuery(obj3);
Cursor c = sh.exeQuery("SELECT param1,param2,param3 FROM table_name WHERE param1 =\"a\" and param2=\"b\" or param3=\"c\"");
Cursor c = sh.exeQuery("SELECT * FROM table_name WHERE _id = ?",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT * FROM table_name"," _id = ? ",new String[]{"whereArg"});
Cursor c = sh.exeQuery("SELECT ? FROM table_name WHERE _id = ?",new String[]{"Field"},new String[]{"whereArg"});
但是,如果您不想使用 exeQuery
,请尝试以下步骤:
queryObject obj = convertQueryStringToQueryObject(query);
Cursor c = this.getContentResolver().query(obj.uri, obj.projection, obj.selection, obj.selectionArgs, null);
来自 android 文档 https://developer.android.com/guide/topics/providers/content-provider-basics#ClientProvider
cursor = getContentResolver().query( UserDictionary.Words.CONTENT_URI, // The content URI of the words table projection, // The columns to return for each row selectionClause, // Selection criteria selectionArgs, // Selection criteria sortOrder); // The sort order for the returned rows
你可以做到
String[] projection = {"*"};
String[] selectionArgs = {"1", "2"}; //your ids here
Cursor cursor = getContentResolver().query(Uri.parse("content://your_provider/your_table"), projection, "_id", selectionArgs, null);
cursor.close();
要创建提供商,请参阅此 https://developer.android.com/guide/topics/providers/content-provider-creating#top_of_page
也看到这个答案