Best practices/correct way to upgrade your local base

Asked

Viewed 54 times

3

Good morning, I got an APP started by a colleague in the company. The problem is that I’m not flying yet with android. I need to make changes to the structure of the local bank (With the APP in production), my doubt is in the execution of the onUpgrade method. I will try to describe the scenario of the APP when I took: Each Models file has another Dbhandler file, which iterates with the database (Inserts, queries...). Each Dbhandler had the CREATE TABLE of the tables referring to its Model, in addition to all having the variables:

private static final int DATABASE_VERSION_PGS = 1;
private static final String DATABASE_NAME_PGS = "database.bd";

I did not see sense in leaving so on all Dbhandler, since in each change of version I would have to change all the files. I created a central store that stores this information and I take it from these variables. The problem is that when I change the version in that file, the onUpgrade method does not run. The question is, did I do it the wrong way? What’s the best/right way? All the documentation I saw said - summarizing - that onUpgrade was the method used to update the bank structure and for that it was only to change the version.

It follows code excerpt from the Familiesdbhandler file, after I centralized this information:

public class FamiliesDBHandler extends SQLiteOpenHelper {


        private static final int DATABASE_VERSION_PGS = Config.getDatabaseVersion();
        private static final String DATABASE_NAME_PGS = Config.getDatabaseName();

        public static final String TABLE_NAME_PGS_FAMILIES = "families";
        public static final String COLUMN_ID_PGS_FAMILIES = "_id";
        public static final String COLUMN_NAME_PGS_FAMILIES = "name";
        public static final String COLUMN_CPF_PGS_FAMILIES = "cpf";
        public static final String COLUMN_COUNTY_PGS_FAMILIES = "county";
        public static final String COLUMN_CODE_PGS_FAMILIES = "pgs_code";
        public static final String COLUMN_COUNTY_CODE_PGS_FAMILIES = "county_code";
        public static final String COLUMN_LATITUDE_PGS_FAMILIES = "latitude";
        public static final String COLUMN_LONGITUDE_PGS_FAMILIES = "longitude";
        public static final String COLUMN_EMAIL_OWNER = "email_owner";

        public FamiliesDBHandler(Context context){
            super(context, DATABASE_NAME_PGS, null, DATABASE_VERSION_PGS);
            this.createTableIfNotExistPgs(this.getWritableDatabase());


        }

        public FamiliesDBHandler(Context context, String type){
            super(context, DATABASE_NAME_PGS, null, DATABASE_VERSION_PGS);
        }

        @Override
        public void onCreate(SQLiteDatabase db){}
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
            Log.i("EMATERPGS", "UPGRADE");
            String ALTER_TABLE = "ALTER TABLE "+ TABLE_NAME_PGS_FAMILIES +" ADD COLUMN "+COLUMN_EMAIL_OWNER+" STRING" ;
            try{
                db.execSQL(ALTER_TABLE);
            }catch(SQLiteException e){
                Log.i("EMATERPGS", e.getMessage());
            }
        }

        public boolean createTableIfNotExistPgs(SQLiteDatabase db){
            boolean returnStatus = true;

            String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS "+ TABLE_NAME_PGS_FAMILIES +" (" +
                    COLUMN_ID_PGS_FAMILIES +" INTEGER PRIMARY KEY AUTOINCREMENT," +
                    COLUMN_NAME_PGS_FAMILIES +" TEXT," +
                    COLUMN_CPF_PGS_FAMILIES +" TEXT," +
                    COLUMN_COUNTY_PGS_FAMILIES +" TEXT," +
                    COLUMN_CODE_PGS_FAMILIES +" INTEGER," +
                    COLUMN_COUNTY_CODE_PGS_FAMILIES +" TEXT," +
                    COLUMN_LATITUDE_PGS_FAMILIES +" DOUBLE," +
                    COLUMN_LONGITUDE_PGS_FAMILIES +" DOUBLE);";
            try{
                db.execSQL(CREATE_TABLE);
            }catch(SQLiteException e){
                returnStatus = false;
            }

            return returnStatus;
        }
}

Archive where I centralized the information:

public class Config {
    //DATABASE
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "database.db";

    public static int getDatabaseVersion() {
        return DATABASE_VERSION;
    }

    public static String getDatabaseName() {
            return DATABASE_NAME;
    }
}

[EDIT] Information that may be relevant in the case of: When I change the version in all the files, e.g.: Step of

private static final int DATABASE_VERSION_PGS = 1;

for

private static final int DATABASE_VERSION_PGS = 2;

onUpgrade does not run, but when I change in only one file, the onUpgrade of that file runs, but ai error in the APP (I believe for having more than one database version in the code).

  • I think your question might be more complete if you put your code in for analysis. This issue of Onupgrade is very broad and depends a lot on how you are implementing the database whether it is via Helper or whether it is using a ORM.

  • To be honest, for me it did not work alter table, I needed to create a new backup table, pass the values of the old table, delete and create the old table with some new column you want, and pass the values of the backup table to this new table, then delete the backup table. For me this was the only solution.

  • Okay, I found the motive. In the Activity Main of the APP all *Dbhandler are staged (by the logic, so that every bank was created) it happens that when I change the version of the bank onUpgrade runs, but only the one of the first instance. All other instances do not perform onUpgrade. This pq in practice, the bank is updated in the first instance. I can try to be clearer

  • Thanks Murilo, I saw a lot of this during my research. But it was not my case. It is that as the APP was all developed by someone else, it made my understanding difficult. But just the fact that I asked the question here helped in the way I looked at the code..

  • I understand, if you found the problem, it would be interesting to answer your own question, to help others with the same or similar problem.

  • Yes, I agree. I still have a doubt about the way the bank is created. In my mainActivity all *Dbhandler are created as I said in the other comment. Each Dbhandler creates a table: activitiesDBHandler = new ActivitiesDBHandler(getBaseContext()); familiesDBHandler = new FamiliesDBHandler(getBaseContext()); familyActivitiesDBHandler = new familyActivitiesDBHandler(getBaseContext()); That is, when I change the bank version only the first instance will run onUpgrade. That’s the question, I should migrate the creation of the entire bank into one file?

  • In that I can not help, I do not know if it is best practice, but I usually create in a single Dbhandler

Show 2 more comments

1 answer

1


After asking this question and searching for answers on the web, I paid more attention to my mainActivity code. It turns out that there, all these *Dbhandler are instantiated (Code below), I believe that in order for the entire bank to be created.

//DATABASE//
        try{
            activitiesDBHandler = new ActivitiesDBHandler(getBaseContext());
            familiesDBHandler = new FamiliesDBHandler(getBaseContext());
            familyActivitiesDBHandler = new FamilyActivitiesDBHandler(getBaseContext());
            activityProductTypesDBHandler = new ProductTypesDBHandler(getBaseContext());
            costTypesDBHandler = new CostTypesDBHandler(getBaseContext());
            areaTypesDBHandler = new AreaTypesDBHandler(getBaseContext());
            laborForceDBHandler = new LaborForceDBHandler(getBaseContext());
            laborForceTypesDBHandler = new LaborForceTypesDBHandler(getBaseContext());
            animalDBHandler = new AnimalDBHandler(getBaseContext());
            animalTypeDBHandler = new AnimalTypeDBHandler(getBaseContext());
            expenseDBHandler = new ExpenseDBHandler(getBaseContext());
            otherRecipeTypeDBHandler = new OtherRecipeTypeDBHandler(getBaseContext());
            managementPlainPeriodDBHandler = new ManagementPlainPeriodDBHandler(getBaseContext());
            managementPlainDBHandler = new ManagementPlainDBHandler(getBaseContext());
            planningMatrixDBHandler = new PlanningMatrixDBHandler(getBaseContext());
            planningMatrixActionDBHandler = new PlanningMatrixActionDBHandler(getBaseContext());
            plannedSituationDBHandler = new PlannedSituationDBHandler(getBaseContext());
            calendarOfActionDBHandler = new CalendarOfActionDBHandler(getBaseContext());
            calendarOfActionYearsDBHandler = new CalendarOfActionYearsDBHandler(getBaseContext());
            buildingMachineDBHandler = new BuildingMachineDBHandler(getBaseContext());
            indirectExpenseDBHandler = new IndirectExpenseDBHandler(getBaseContext());
            logsDBHandler = new LogsDBHandler(getBaseContext());
            localLoginDBHandler = new LocalLoginDBHandler(getBaseContext());
        }catch(SQLiteException e){
            Log.i("TAG", "ERROR "+e.getMessage());
        }
        //DATABASE//

How all these *Dbhandler extend the class Sqliteopenhelper, each of them has its onCreate and onUpgrade methods. And when I changed the version of the bank in my central settings file the APP ran onUpgrade, but only onUpgrade of the first instance. In other instances the version of the bank is already updated, so the method is not called. In this case I decided to leave the instance of the table that I wanted to change as the first of the row. It’s a very specific and particular case I believe, but I hope it helps someone not to do it that way. Because the moment I need to change several tables of the bank, this form of development will not allow me. I believe that the best way would be to pass all the creation of the base structure to just one file.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.