Multiple Table SQLite DB Adapter(s) in Android?

后端 未结 2 1794
臣服心动
臣服心动 2020-11-29 14:49

I was reading the Android SQLite NotePad tutorial that referenced creating a DB Adapter class to create and access a DB table. When dealing with a multi-table SQLite Databa

相关标签:
2条回答
  • 2020-11-29 15:35

    Here is the solution I eventually ended up implementing. It's kind of a mash-up from info gained in the Commonsware books, and some stuff around the web that I wish I bookmarked cause I want to give credit:

    For each type of data that I need to pull from the db, I create an "adapter" class (not subclassed from anything). These adapter classes hold all of the methods necessary for accessing the db for that piece of info. For example, if I had three tables in my db:

    1. Cars
    2. Boats
    3. Motorcycles

    I would have three adapters that would look similar to the following(I'm only putting in one as a demo, but the idea is the same for each):

    public class CarsDBAdapter {
        public static final String ROW_ID = "_id";
        public static final String NAME = "name";
        public static final String MODEL = "model";
        public static final String YEAR = "year";
    
        private static final String DATABASE_TABLE = "cars";
    
        private DatabaseHelper mDbHelper;
        private SQLiteDatabase mDb;
    
        private final Context mCtx;
    
        private static class DatabaseHelper extends SQLiteOpenHelper {
    
            DatabaseHelper(Context context) {
                super(context, DBAdapter.DATABASE_NAME, null, DBAdapter.DATABASE_VERSION);
            }
    
            @Override
            public void onCreate(SQLiteDatabase db) {
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            }
        }
    
        /**
         * Constructor - takes the context to allow the database to be
         * opened/created
         * 
         * @param ctx
         *            the Context within which to work
         */
        public CarsDBAdapter(Context ctx) {
            this.mCtx = ctx;
        }
    
        /**
         * Open the cars database. If it cannot be opened, try to create a new
         * instance of the database. If it cannot be created, throw an exception to
         * signal the failure
         * 
         * @return this (self reference, allowing this to be chained in an
         *         initialization call)
         * @throws SQLException
         *             if the database could be neither opened or created
         */
        public CarsDBAdapter open() throws SQLException {
            this.mDbHelper = new DatabaseHelper(this.mCtx);
            this.mDb = this.mDbHelper.getWritableDatabase();
            return this;
        }
    
        /**
         * close return type: void
         */
        public void close() {
            this.mDbHelper.close();
        }
    
        /**
         * Create a new car. If the car is successfully created return the new
         * rowId for that car, otherwise return a -1 to indicate failure.
         * 
         * @param name
         * @param model
         * @param year
         * @return rowId or -1 if failed
         */
        public long createCar(String name, String model, String year){
            ContentValues initialValues = new ContentValues();
            initialValues.put(NAME, name);
            initialValues.put(MODEL, model);
            initialValues.put(YEAR, year);
            return this.mDb.insert(DATABASE_TABLE, null, initialValues);
        }
    
        /**
         * Delete the car with the given rowId
         * 
         * @param rowId
         * @return true if deleted, false otherwise
         */
        public boolean deleteCar(long rowId) {
    
            return this.mDb.delete(DATABASE_TABLE, ROW_ID + "=" + rowId, null) > 0; //$NON-NLS-1$
        }
    
        /**
         * Return a Cursor over the list of all cars in the database
         * 
         * @return Cursor over all cars
         */
        public Cursor getAllCars() {
    
            return this.mDb.query(DATABASE_TABLE, new String[] { ROW_ID,
                    NAME, MODEL, YEAR }, null, null, null, null, null);
        }
    
        /**
         * Return a Cursor positioned at the car that matches the given rowId
         * @param rowId
         * @return Cursor positioned to matching car, if found
         * @throws SQLException if car could not be found/retrieved
         */
        public Cursor getCar(long rowId) throws SQLException {
    
            Cursor mCursor =
    
            this.mDb.query(true, DATABASE_TABLE, new String[] { ROW_ID, NAME,
                    MODEL, YEAR}, ROW_ID + "=" + rowId, null, null, null, null, null);
            if (mCursor != null) {
                mCursor.moveToFirst();
            }
            return mCursor;
        }
    
        /**
         * Update the car.
         * 
         * @param rowId
         * @param name
         * @param model
         * @param year
         * @return true if the note was successfully updated, false otherwise
         */
        public boolean updateCar(long rowId, String name, String model,
                String year){
            ContentValues args = new ContentValues();
            args.put(NAME, name);
            args.put(MODEL, model);
            args.put(YEAR, year);
    
            return this.mDb.update(DATABASE_TABLE, args, ROW_ID + "=" + rowId, null) >0; 
        }
    
    }
    

    So if you imagine I have one of these classes "adapters" for each table.

    When my app splash screen starts, I use the technique presented Android For Beginners: Creating multiple SQLite Tables for Android

    So my main DBAdapter (which is responsible for creating all of my tables in a single db) looks like this:

    public class DBAdapter {
    
        public static final String DATABASE_NAME = "stuffIOwn"; //$NON-NLS-1$
    
        public static final int DATABASE_VERSION = 1;
    
        private static final String CREATE_TABLE_CARS =
           "create table cars (_id integer primary key autoincrement, " //$NON-NLS-1$
        + CarsDBAdapter.NAME+ " TEXT," //$NON-NLS-1$
        + CarsDBAdapter.MODEL+ " TEXT," //$NON-NLS-1$
        + CarsDBAdapter.YEAR+ " TEXT" + ");"; //$NON-NLS-1$ //$NON-NLS-2$
    
        private static final String CREATE_TABLE_BOATS = "create table boats (_id integer primary key autoincrement, " //$NON-NLS-1$
        +BoatsDBAdapter.NAME+" TEXT," //$NON-NLS-1$
        +BoatsDBAdapter.MODEL+" TEXT," //$NON-NLS-1$
        +BoatsDBAdapter.YEAR+" TEXT"+ ");"; //$NON-NLS-1$  //$NON-NLS-2$
    
            private static final String CREATE_TABLE_CYCLES = "create table cycles (_id integer primary key autoincrement, " //$NON-NLS-1$
        +CyclesDBAdapter.NAME+" TEXT," //$NON-NLS-1$
        +CyclesDBAdapter.MODEL+" TEXT," //$NON-NLS-1$
        +CyclesDBAdapter.YEAR+" TEXT"+ ");"; //$NON-NLS-1$  //$NON-NLS-2$
    
    
        private final Context context; 
        private DatabaseHelper DBHelper;
        private SQLiteDatabase db;
    
        /**
         * Constructor
         * @param ctx
         */
        public DBAdapter(Context ctx)
        {
            this.context = ctx;
            this.DBHelper = new DatabaseHelper(this.context);
        }
    
        private static class DatabaseHelper extends SQLiteOpenHelper 
        {
            DatabaseHelper(Context context) 
            {
                super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }
    
            @Override
            public void onCreate(SQLiteDatabase db) 
            {
                db.execSQL(CREATE_TABLE_CARS);
                db.execSQL(CREATE_TABLE_BOATS);
                db.execSQL(CREATE_TABLE_CYCLES);           
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, 
            int newVersion) 
            {               
                // Adding any table mods to this guy here
            }
        } 
    
       /**
         * open the db
         * @return this
         * @throws SQLException
         * return type: DBAdapter
         */
        public DBAdapter open() throws SQLException 
        {
            this.db = this.DBHelper.getWritableDatabase();
            return this;
        }
    
        /**
         * close the db 
         * return type: void
         */
        public void close() 
        {
            this.DBHelper.close();
        }
    }
    

    The DBAdapter class only gets called when the app first starts and its only responsibility is to create/upgrade the tables. All other access to the data is done through the individual "adapter" class. I've found that this works perfectly and does not create the versioning issues that I mentioned earlier.

    Hope this helps.

    0 讨论(0)
  • 2020-11-29 15:48

    Had the same problem, tried many solutions, finnaly i made an abstract method wich constructs the database structure and has extended class for the table classes.

    This is my Database constructor class and is Abstract:

    public abstract class dbAdapter {
        public static String DATABASE_NAME = "";
        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_TABLE1 = "ContactName";
        public static final String DATABASE_TABLE2 = "PhoneNumber";
    
        public static DbHelper ourHelper;
        public static Context ourContext;
        public static SQLiteDatabase ourDatabase;
    
        boolean ourConstructorBool = false;
        boolean ourDB = false;
    
        public static final String ContactNameTable = "CREATE TABLE "+DATABASE_TABLE1+" (" +
            ContactNameAdapter.KEY_ROWID+" INTEGER PRIMARY KEY AUTOINCREMENT, " +
            ContactNameAdapter.KEY_NAME+" TEXT, " +
            ContactNameAdapter.KEY_BIRTH_DATE+" TEXT);";
    
        public static final String PhoneNumberTable = "CREATE TABLE "+DATABASE_TABLE2+" (" + 
            PhoneNumberAdapter.KEY_NUMBER+" TEXT , " +
            PhoneNumberAdapter.KEY_DESCRIPTION+" TEXT, " +
            PhoneNumberAdapter.KEY_CONTACTID+" TEXT, " +
            "FOREIGN KEY(" + PhoneNumberAdapter.KEY_CONTACTID +") REFERENCES " +
            (ContactNameAdapter.DATABASE_TABLE)+"("+ContactNameAdapter.KEY_ROWID+") ON DELETE CASCADE"+
        ");";
    
        static class DbHelper extends SQLiteOpenHelper{
            public DbHelper(Context context) {
                super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }
            @Override
            public void onCreate(SQLiteDatabase db) {
                db.execSQL(ContactNameTable);
                db.execSQL(PhoneNumberTable);
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
                db.execSQL("DROP TABLE IF EXISTS " + ContactNameAdapter.DATABASE_TABLE);
                db.execSQL("DROP TABLE IF EXISTS " + PhoneNumberAdapter.DATABASE_TABLE);
                onCreate(db);
            }
        }
    
        public dbAdapter(Activity a){   
            if(!ourConstructorBool == true){
                ourContext = a;
                DATABASE_NAME = a.getString(Asaf.com.contactsEX.R.string.DB_NAME);
                ourConstructorBool = true;
            }
        }
    
        public dbAdapter open() throws SQLException{
            if(!ourDB == true){
                ourHelper = new DbHelper(ourContext);
                ourDB = true;
            }
            ourDatabase = ourHelper.getWritableDatabase();
            return this;
        }
    
        public void close(){
            if(ourDatabase.isOpen())
                ourHelper.close();
        }
    }
    

    And this is one of my table classes, the rest of the classes are implemented the same, just add as much as you like:

    public class PhoneNumberAdapter extends dbAdapter{
    
        public static final String KEY_NUMBER = "PhoneNumber";
        public static final String KEY_DESCRIPTION = "Description";
        public static final String KEY_CONTACTID = "ContactName_id";
    
        public static final String DATABASE_TABLE = "PhoneNumber";
    
        public PhoneNumberAdapter(Activity a){
            super(a);
        }
    
        public long createEntry(String number, String description,long id){
            // TODO Auto-generated method stub
            ContentValues cv = new ContentValues();
            cv.put(KEY_NUMBER, number);
            cv.put(KEY_DESCRIPTION, description);
            cv.put(KEY_CONTACTID, id);
            return ourDatabase.insert(DATABASE_TABLE, null,cv);
        }
    }
    

    Hope I helped.

    0 讨论(0)
提交回复
热议问题