How to implement a content provider with more than one table?

后端 未结 3 1941
傲寒
傲寒 2021-02-06 19:29

update: looking at \"vnd.android.cursor.dir/vnd.google.note\" and \"vnd.android.cursor.item/vnd.google.note\" it seemed to me as thoug

相关标签:
3条回答
  • 2021-02-06 20:07

    Here is my code for multiple table query in content provider with 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'
    
    0 讨论(0)
  • 2021-02-06 20:17

    When creating a ContentProvider, the expectation is that other apps are going to use your database, and with that I mean other people who know nothing about your database scheme. To make things easy for them, you create and document your URIs:

    To access all the books

    content://org.example.bookprovider/books
    

    to access books by id

    content://org.example.bookprovider/books/#
    

    to access books by author name

    content://org.example.bookprovider/books/author
    

    Create as many URIs as you need, that’s up to you. This way the user of your Provider can very easily access your database info, and maybe that’s why you are getting the impression that the Provider is designed to work with one table databases, but no, internally is where the work is done.

    In your ContentProvider subclass, you can use a UriMatcher to identify those different URIs that are going to be passed to your ContentProvider methods (query, insert, update, delete). If the data the Uri is requesting is stored in several tables, you can actually do the JOINs and GROUP BYs or whatever you need with SQLiteQueryBuilder , e.g.

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

    Hope it helps.

    0 讨论(0)
  • 2021-02-06 20:26

    Excuse me, but I don't understand your question.

    ContentProvider is designed (a one of it's aims)to wrap access to your tabels. Design of database schema is up to you.

    Generally, you need to:

    1. Define your tables/ It should be made by execution of sql command in class which extends SQLiteOpenHelper
    2. Define an uri for them
    3. Define a logic for queries to this tables as it was made for NOTE_ID

    Update For JOIN operations SQLiteQueryBuilder is usually used. In setTables() you need to write names of tables with JOIN clause, e.g.

    .setTables(NoteColumns.TABLENAME +
                " LEFT OUTER JOIN " + TopicColumns.TABLENAME + " ON " +
                NoteColumns.ID + " = " + TopicColumns.ID);
    
    0 讨论(0)
提交回复
热议问题