更新:在我看来"vnd.android.cursor.dir/vnd.google.note"
和"vnd.android.cursor.item/vnd.google.note"
,好像光标是一张桌子。
从示例中可以看出内容提供程序设计为使用一个表。我知道如何在sqlite中使用多个表,但在我看来,内容提供者似乎是从一个表中选择一行或多行。
请参阅http://developer.android.com/guide/topics/providers/content-provider-creating.html
另外,请参阅adt-bundle-windows-x86-20131030 \ sdk \ samples \ android-19 \ legacy \ NotePad \ src \ com \ example \ android \ notepad
中的记事本示例假设我想按主题发表评论。
我想要一个包含_id和Title_text列的主题表。 我想让Notes表包含列_id和外键Topic_id和Note_text。
如何设计主题和备注?
但是看看Notes示例,内容提供商上的内容URI和文档,看起来好像有多个相关的表是事后的想法,对我来说并不明显。
来自NotepadProvider.java,Notepad.java:
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";
/**
* The MIME type of a {@link #CONTENT_URI} sub-directory of a single
* note.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";
public static final Uri CONTENT_ID_URI_BASE
= Uri.parse(SCHEME + AUTHORITY + PATH_NOTE_ID);
/**
* The content URI match pattern for a single note, specified by its ID. Use this to match
* incoming URIs or to construct an Intent.
*/
public static final Uri CONTENT_ID_URI_PATTERN
= Uri.parse(SCHEME + AUTHORITY + PATH_NOTE_ID + "/#");
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
...
switch (sUriMatcher.match(uri)) {
// If the incoming URI is for notes, chooses the Notes projection
case NOTES:
qb.setProjectionMap(sNotesProjectionMap);
break;
/* If the incoming URI is for a single note identified by its ID, chooses the
* note ID projection, and appends "_ID = <noteID>" to the where clause, so that
* it selects that single note
*/
case NOTE_ID:
qb.setProjectionMap(sNotesProjectionMap);
qb.appendWhere(
NotePad.Notes._ID + // the name of the ID column
"=" +
// the position of the note ID itself in the incoming URI
uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION));
break;
答案 0 :(得分:10)
创建ContentProvider
时,期望其他应用程序将使用您的数据库,我的意思是其他人对您的数据库方案一无所知。为了方便他们,您可以创建并记录您的URI:
访问所有图书
content://org.example.bookprovider/books
按ID
访问图书content://org.example.bookprovider/books/#
按作者姓名访问图书
content://org.example.bookprovider/books/author
根据需要创建尽可能多的URI,这取决于您。这样,您的提供商的用户可以非常轻松地访问您的数据库信息,也许这就是为什么您会得到供应商旨在使用一个表数据库的印象,但不是,内部是工作完成的地方。
在ContentProvider子类中,您可以使用UriMatcher
来标识将要传递给ContentProvider方法的不同URI(query
,insert
,update
,delete
)。如果Uri
请求的数据存储在多个表中,您实际上可以使用SQLiteQueryBuilder执行JOIN
和GROUP BY
或任何您需要的内容,例如
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder mQueryBuilder = new SQLiteQueryBuilder();
. . .
String Joins = " t1 INNER JOIN table2 t2 ON t2._id = t1._id"
+ " INNER JOIN table3 t3 ON t3._id = t1._id";
switch (mUriMatcher.match(uri)) {
case DATA_COLLECTION_URI:
mQueryBuilder.setTables(YourDataContract.TABLE1_NAME + Joins);
mQueryBuilder.setProjectionMap(. . .);
break;
case SINGLE_DATA_URI:
mQueryBuilder.setTables(YourDataContract.TABLE1_NAME + Joins);
mQueryBuilder.setProjectionMap(. . .);
mQueryBuilder.appendWhere(Table1._ID + "=" + uri.getPathSegments().get(1));
break;
case . . .
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
. . .
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor c = mQueryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, orderBy);
return c;
}
希望它有所帮助。
答案 1 :(得分:1)
对不起,但我不明白你的问题。
ContentProvider旨在(其中一个目标)包装访问您的表格。数据库模式的设计由您决定。
通常,您需要:
<强>更新强>
对于JOIN操作,通常使用SQLiteQueryBuilder
。在setTables()
中,您需要使用JOIN子句编写表的名称,例如
.setTables(NoteColumns.TABLENAME +
" LEFT OUTER JOIN " + TopicColumns.TABLENAME + " ON " +
NoteColumns.ID + " = " + TopicColumns.ID);
答案 2 :(得分:0)
以下是使用projectionMap
在内容提供程序中进行多表查询的代码//HashMap for Projection
mGroupImageUri = new HashMap<>();
mGroupImageUri.put(RosterConstants.JID,RosterProvider.TABLE_ROSTER+"."+RosterConstants.JID);
mGroupImageUri.put(RosterConstants.USER_NAME,RosterProvider.TABLE_ROSTER+"."+RosterConstants.USER_NAME);
mGroupImageUri.put(ChatConstants.MESSAGE,"c."+ChatConstants.MESSAGE+ " AS "+ ChatConstants.MESSAGE);
mGroupImageUri.put(ChatConstants.SENDER,"c."+ChatConstants.SENDER+" AS "+ChatConstants.SENDER);
mGroupImageUri.put(ChatConstants.URL_LOCAL,"c."+ChatConstants.URL_LOCAL+" AS "+ChatConstants.URL_LOCAL);
//case for content type of uri
case IMAGE_URI:
qBuilder.setTables(RosterProvider.TABLE_ROSTER
+ " LEFT OUTER JOIN "+ TABLE_NAME + " c"
+ " ON c."+ ChatConstants.JID + "=" + RosterProvider.TABLE_ROSTER + "."+RosterConstants.JID);
qBuilder.setProjectionMap(mGroupImageUri);
break;
//ContentResolver query for Projection form, selection and selection args
String[] PROJECTION_FROM = new String[]{
RosterConstants.JID,
RosterConstants.USER_NAME,
ChatConstants.MESSAGE,
ChatConstants.SENDER,
ChatConstants.URL_LOCAL
};
String selection = RosterProvider.TABLE_ROSTER +"."+RosterConstants.JID+ "='" + jid + "' AND " + "c."+ChatConstants.FILE_TYPE+"="+ChatConstants.IMAGE;
String[] selectionArgu = null;
String order = "c."+ChatConstants.MESSAGE+" ASC";
Cursor cursor = mContentReolver.query(ChatProvider.CONTENT_URI_GROUP_IMAGE_URI,
PROJECTION_FROM,selection, null,order);
//@ChatProvider.CONTENT_URI_GROUP_IMAGE_URI = 'your content type uri'
//@TABLE_NAME = 'table1'
//@RosterProvider.TABLE_ROSTER ='table2'