A
A
ArtBigTema2016-05-29 11:45:48
Android
ArtBigTema, 2016-05-29 11:45:48

ActiveAndroid, how to add a field (column) without losing data?

The site says that you need to raise the version of the database (AA_DB_VERSION), but there is no sense, when you save () an existing class instance, the application crashes.
Who uses this ORM, how do you update, add fields?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
Z
z0rgoyok, 2016-05-29
@z0rgoyok

ActiveAndroid adds new tables well , but not fields, fields need migrations. For automation, I made such a crutch:

public void upgrade(Context context) {
        //надо найти файл с описанием прошлой базы
        //в ней есть версия
        /*если новая версия больше - посмотреть какие поля есть в моделях, которых нет в файле описания
                если такие есть - добавить
                создать новый файл описания*/

        String path = context.getFilesDir().getAbsolutePath() + "/db_version.txt";
        File file = new File(path);

        int lastDBVersion = -1;
        boolean needCreateFile = false;
        boolean needApplyUpdates = false;
        List<String> savedFields = null;

        //файл существует
        if (file.exists()) {
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(file));
                String line = br.readLine();
                lastDBVersion = Integer.parseInt(line);
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                try {
                    if (br != null) {
                        br.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            //
            needApplyUpdates = true;
        }

        //костыль при переходе на версию
        //boolean needChangeEventTypeValue = false;
        //dbVersion += 1;

        if (lastDBVersion != -1 && lastDBVersion < dbVersion) {
            needApplyUpdates = true;
        }

        if (needApplyUpdates) {

            //читаем старый список
            savedFields = new ArrayList<>();

            //создаем список из полей в бд
            for (Class classModel : models) {
                String tableName = getTableName(classModel);

                Cursor cursor = ActiveAndroid.getDatabase().rawQuery("PRAGMA table_info(" + tableName + ")", null);
                try {
                    int nameIdx = cursor.getColumnIndexOrThrow("name");
                    int typeIdx = cursor.getColumnIndexOrThrow("type");
                    while (cursor.moveToNext()) {
                        String type = cursor.getString(typeIdx);
                        String name = cursor.getString(nameIdx);
                        savedFields.add(tableName + "." + name + "." + type);
                    }
                } finally {
                    cursor.close();
                }
            }

            //создаем новый список
            List<FieldClassStruct> newFields = new ArrayList<>();
            for (Class model : models) {
                Set<Field> modelFields = getClassFields(model);
                for (Field field : modelFields) {
                    newFields.add(new FieldClassStruct(field, model));
                }
            }

            try {
                //ActiveAndroid.beginTransaction();
                //сравниваем новый список со старым
                for (FieldClassStruct newField : newFields) {
                    if (!savedFields.contains(newField.getDesc())) {
                        makeAlterForField(newField);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                /*ActiveAndroid.setTransactionSuccessful();
                ActiveAndroid.endTransaction();*/
            }
        }

        /*ActiveAndroid.dispose();
        ActiveAndroid.initialize(configurationBuilder.create());*/

        //сохраняем новый список

        file.delete();

        BufferedWriter wr = null;
        try {
            wr = new BufferedWriter(new FileWriter(file));
            wr.write(dbVersion + "\n");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (wr != null) {
                try {
                    wr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

A
ArtBigTema, 2016-05-29
@ArtBigTema

I decided, nevertheless, by myself: (Works without upgrading the version)

Cursor c = ActiveAndroid.getDatabase().rawQuery(new Select().from(Post.class).toSql(), null);
  String[] names = c.getColumnNames();//список всех полей БД

  String[] newColumns = DbActiveHelper.getNewColumnNames(names, ActiveAndroid.getDatabase().getVersion());
        // новые поля, корых нет в списке names

for (String s : newColumns) {
            try {
                ActiveAndroid.getDatabase().execSQL("ALTER TABLE Post ADD COLUMN " + s); // s == "field INTEGER"
            } catch (SQLException e) {
                Log.e(TAG, e.getMessage());
            }
        }

How to reduce the fields, I have not yet found.
Might help someone in the future

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question