2

I am using DBflow in my application right now and I wanted to modify a table by inserting a new column called categoryId. So I searched a little bit and I found out that I had to write a migration script to handle this modification in my table "Task". The problem is that I don't know what went wrong, but I got an error saying that there was no such column.

I uninstalled the app and install it back again and it worked just fine. The problem is that I have some other users getting the same error and I don't know what is causing it.

/**
 * This is generated code. Please do not modify */
public final class Task_Table extends ModelAdapter<Task> {
  /**
   * Primary Key */
  public static final Property<String> id = new Property<String>(Task.class, "id");

  public static final Property<String> project_id = new Property<String>(Task.class, "project_id");

  public static final Property<String> title = new Property<String>(Task.class, "title");

  public static final Property<String> description = new Property<String>(Task.class, "description");

  public static final Property<String> collection_id = new Property<String>(Task.class, "collection_id");

  public static final Property<Integer> priority = new Property<Integer>(Task.class, "priority");

  public static final TypeConvertedProperty<Long, Date> created_at = new TypeConvertedProperty<Long, Date>(Task.class, "created_at", true,
  new TypeConvertedProperty.TypeConverterGetter() {
  @Override
  public TypeConverter getTypeConverter(Class<?> modelClass) {
    Task_Table adapter = (Task_Table) FlowManager.getInstanceAdapter(modelClass);
  return adapter.global_typeConverterDateConverter;
  }
  });

  public static final Property<String> created_by = new Property<String>(Task.class, "created_by");

  public static final TypeConvertedProperty<Long, Date> updated_at = new TypeConvertedProperty<Long, Date>(Task.class, "updated_at", true,
  new TypeConvertedProperty.TypeConverterGetter() {
  @Override
  public TypeConverter getTypeConverter(Class<?> modelClass) {
    Task_Table adapter = (Task_Table) FlowManager.getInstanceAdapter(modelClass);
  return adapter.global_typeConverterDateConverter;
  }
  });

  public static final TypeConvertedProperty<Long, Date> due_date = new TypeConvertedProperty<Long, Date>(Task.class, "due_date", true,
  new TypeConvertedProperty.TypeConverterGetter() {
  @Override
  public TypeConverter getTypeConverter(Class<?> modelClass) {
    Task_Table adapter = (Task_Table) FlowManager.getInstanceAdapter(modelClass);
  return adapter.global_typeConverterDateConverter;
  }
  });

  public static final TypeConvertedProperty<Long, Date> completed_at = new TypeConvertedProperty<Long, Date>(Task.class, "completed_at", true,
  new TypeConvertedProperty.TypeConverterGetter() {
  @Override
  public TypeConverter getTypeConverter(Class<?> modelClass) {
    Task_Table adapter = (Task_Table) FlowManager.getInstanceAdapter(modelClass);
  return adapter.global_typeConverterDateConverter;
  }
  });

  public static final Property<String> completed_by = new Property<String>(Task.class, "completed_by");

  public static final Property<String> categoryId = new Property<String>(Task.class, "categoryId");

  public static final Property<Integer> feed_count = new Property<Integer>(Task.class, "feed_count");

  public static final Property<Integer> read_count = new Property<Integer>(Task.class, "read_count");

  public static final IProperty[] ALL_COLUMN_PROPERTIES = new IProperty[]{id,project_id,title,description,collection_id,priority,created_at,created_by,updated_at,due_date,completed_at,completed_by,categoryId,feed_count,read_count};

  private final DateConverter global_typeConverterDateConverter;

  public Task_Table(DatabaseHolder holder, DatabaseDefinition databaseDefinition) {
    super(databaseDefinition);
    global_typeConverterDateConverter = (DateConverter) holder.getTypeConverterForClass(Date.class);
  }

  @Override
  public final Class<Task> getModelClass() {
    return Task.class;
  }

  @Override
  public final String getTableName() {
    return "`Task`";
  }

  @Override
  public final Task newInstance() {
    return new Task();
  }

  @Override
  public final Property getProperty(String columnName) {
    columnName = QueryBuilder.quoteIfNeeded(columnName);
    switch ((columnName)) {
      case "`id`":  {
        return id;
      }
      case "`project_id`":  {
        return project_id;
      }
      case "`title`":  {
        return title;
      }
      case "`description`":  {
        return description;
      }
      case "`collection_id`":  {
        return collection_id;
      }
      case "`priority`":  {
        return priority;
      }
      case "`created_at`":  {
        return created_at;
      }
      case "`created_by`":  {
        return created_by;
      }
      case "`updated_at`":  {
        return updated_at;
      }
      case "`due_date`":  {
        return due_date;
      }
      case "`completed_at`":  {
        return completed_at;
      }
      case "`completed_by`":  {
        return completed_by;
      }
      case "`categoryId`":  {
        return categoryId;
      }
      case "`feed_count`":  {
        return feed_count;
      }
      case "`read_count`":  {
        return read_count;
      }
      default: {
        throw new IllegalArgumentException("Invalid column name passed. Ensure you are calling the correct table's column");
      }
    }
  }

  @Override
  public final IProperty[] getAllColumnProperties() {
    return ALL_COLUMN_PROPERTIES;
  }

  @Override
  public final void bindToInsertValues(ContentValues values, Task model) {
    values.put("`id`", model.getId() != null ? model.getId() : null);
    values.put("`project_id`", model.getProjectId() != null ? model.getProjectId() : null);
    values.put("`title`", model.getTitle() != null ? model.getTitle() : null);
    values.put("`description`", model.getDescription() != null ? model.getDescription() : null);
    values.put("`collection_id`", model.getCollectionId() != null ? model.getCollectionId() : null);
    values.put("`priority`", model.getPriority());
    Long refmCreatedAt = model.getCreatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCreatedAt()) : null;
    values.put("`created_at`", refmCreatedAt != null ? refmCreatedAt : null);
    values.put("`created_by`", model.getCreatedById() != null ? model.getCreatedById() : null);
    Long refmUpdatedAt = model.getUpdatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getUpdatedAt()) : null;
    values.put("`updated_at`", refmUpdatedAt != null ? refmUpdatedAt : null);
    Long refmDueDate = model.getDueDate() != null ? global_typeConverterDateConverter.getDBValue(model.getDueDate()) : null;
    values.put("`due_date`", refmDueDate != null ? refmDueDate : null);
    Long refmCompletedAt = model.getCompletedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCompletedAt()) : null;
    values.put("`completed_at`", refmCompletedAt != null ? refmCompletedAt : null);
    values.put("`completed_by`", model.getCompletedById() != null ? model.getCompletedById() : null);
    values.put("`categoryId`", model.getCategoryId() != null ? model.getCategoryId() : null);
    values.put("`feed_count`", model.getFeedCount());
    values.put("`read_count`", model.getReadCount());
  }

  @Override
  public final void bindToInsertStatement(DatabaseStatement statement, Task model, int start) {
    statement.bindStringOrNull(1 + start, model.getId());
    statement.bindStringOrNull(2 + start, model.getProjectId());
    statement.bindStringOrNull(3 + start, model.getTitle());
    statement.bindStringOrNull(4 + start, model.getDescription());
    statement.bindStringOrNull(5 + start, model.getCollectionId());
    statement.bindLong(6 + start, model.getPriority());
    Long refmCreatedAt = model.getCreatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCreatedAt()) : null;
    statement.bindNumberOrNull(7 + start, refmCreatedAt);
    statement.bindStringOrNull(8 + start, model.getCreatedById());
    Long refmUpdatedAt = model.getUpdatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getUpdatedAt()) : null;
    statement.bindNumberOrNull(9 + start, refmUpdatedAt);
    Long refmDueDate = model.getDueDate() != null ? global_typeConverterDateConverter.getDBValue(model.getDueDate()) : null;
    statement.bindNumberOrNull(10 + start, refmDueDate);
    Long refmCompletedAt = model.getCompletedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCompletedAt()) : null;
    statement.bindNumberOrNull(11 + start, refmCompletedAt);
    statement.bindStringOrNull(12 + start, model.getCompletedById());
    statement.bindStringOrNull(13 + start, model.getCategoryId());
    statement.bindLong(14 + start, model.getFeedCount());
    statement.bindLong(15 + start, model.getReadCount());
  }

  @Override
  public final void bindToUpdateStatement(DatabaseStatement statement, Task model) {
    statement.bindStringOrNull(1, model.getId());
    statement.bindStringOrNull(2, model.getProjectId());
    statement.bindStringOrNull(3, model.getTitle());
    statement.bindStringOrNull(4, model.getDescription());
    statement.bindStringOrNull(5, model.getCollectionId());
    statement.bindLong(6, model.getPriority());
    Long refmCreatedAt = model.getCreatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCreatedAt()) : null;
    statement.bindNumberOrNull(7, refmCreatedAt);
    statement.bindStringOrNull(8, model.getCreatedById());
    Long refmUpdatedAt = model.getUpdatedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getUpdatedAt()) : null;
    statement.bindNumberOrNull(9, refmUpdatedAt);
    Long refmDueDate = model.getDueDate() != null ? global_typeConverterDateConverter.getDBValue(model.getDueDate()) : null;
    statement.bindNumberOrNull(10, refmDueDate);
    Long refmCompletedAt = model.getCompletedAt() != null ? global_typeConverterDateConverter.getDBValue(model.getCompletedAt()) : null;
    statement.bindNumberOrNull(11, refmCompletedAt);
    statement.bindStringOrNull(12, model.getCompletedById());
    statement.bindStringOrNull(13, model.getCategoryId());
    statement.bindLong(14, model.getFeedCount());
    statement.bindLong(15, model.getReadCount());
    statement.bindStringOrNull(16, model.getId());
  }

  @Override
  public final void bindToDeleteStatement(DatabaseStatement statement, Task model) {
    statement.bindStringOrNull(1, model.getId());
  }

  @Override
  public final String getCompiledStatementQuery() {
    return "INSERT INTO `Task`(`id`,`project_id`,`title`,`description`,`collection_id`,`priority`,`created_at`,`created_by`,`updated_at`,`due_date`,`completed_at`,`completed_by`,`categoryId`,`feed_count`,`read_count`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
  }

  @Override
  public final String getUpdateStatementQuery() {
    return "UPDATE `Task` SET `id`=?,`project_id`=?,`title`=?,`description`=?,`collection_id`=?,`priority`=?,`created_at`=?,`created_by`=?,`updated_at`=?,`due_date`=?,`completed_at`=?,`completed_by`=?,`categoryId`=?,`feed_count`=?,`read_count`=? WHERE `id`=?";
  }

  @Override
  public final String getDeleteStatementQuery() {
    return "DELETE FROM `Task` WHERE `id`=?";
  }

  @Override
  public final String getCreationQuery() {
    return "CREATE TABLE IF NOT EXISTS `Task`(`id` TEXT, `project_id` TEXT, `title` TEXT, `description` TEXT, `collection_id` TEXT, `priority` INTEGER, `created_at` TEXT, `created_by` TEXT, `updated_at` TEXT, `due_date` TEXT, `completed_at` TEXT, `completed_by` TEXT, `categoryId` TEXT, `feed_count` INTEGER, `read_count` INTEGER, PRIMARY KEY(`id`))";
  }

  @Override
  public final void loadFromCursor(FlowCursor cursor, Task model) {
    model.setId(cursor.getStringOrDefault("id"));
    model.setProjectId(cursor.getStringOrDefault("project_id"));
    model.setTitle(cursor.getStringOrDefault("title"));
    model.setDescription(cursor.getStringOrDefault("description"));
    model.setCollectionId(cursor.getStringOrDefault("collection_id"));
    model.setPriority(cursor.getIntOrDefault("priority"));
    int index_created_at = cursor.getColumnIndex("created_at");
    if (index_created_at != -1 && !cursor.isNull(index_created_at)) {
      model.setCreatedAt(global_typeConverterDateConverter.getModelValue(cursor.getLong(index_created_at)));
    } else {
      model.setCreatedAt(global_typeConverterDateConverter.getModelValue(null));
    }
    model.setCreatedById(cursor.getStringOrDefault("created_by"));
    int index_updated_at = cursor.getColumnIndex("updated_at");
    if (index_updated_at != -1 && !cursor.isNull(index_updated_at)) {
      model.setUpdatedAt(global_typeConverterDateConverter.getModelValue(cursor.getLong(index_updated_at)));
    } else {
      model.setUpdatedAt(global_typeConverterDateConverter.getModelValue(null));
    }
    int index_due_date = cursor.getColumnIndex("due_date");
    if (index_due_date != -1 && !cursor.isNull(index_due_date)) {
      model.setDueDate(global_typeConverterDateConverter.getModelValue(cursor.getLong(index_due_date)));
    } else {
      model.setDueDate(global_typeConverterDateConverter.getModelValue(null));
    }
    int index_completed_at = cursor.getColumnIndex("completed_at");
    if (index_completed_at != -1 && !cursor.isNull(index_completed_at)) {
      model.setCompletedAt(global_typeConverterDateConverter.getModelValue(cursor.getLong(index_completed_at)));
    } else {
      model.setCompletedAt(global_typeConverterDateConverter.getModelValue(null));
    }
    model.setCompletedById(cursor.getStringOrDefault("completed_by"));
    model.setCategoryId(cursor.getStringOrDefault("categoryId"));
    model.setFeedCount(cursor.getIntOrDefault("feed_count"));
    model.setReadCount(cursor.getIntOrDefault("read_count"));
    model.loadPermissions();
    model.loadChecklists();
    model.loadMarkers();
    model.loadAttachments();
  }

  @Override
  public final boolean exists(Task model, DatabaseWrapper wrapper) {
    return SQLite.selectCountOf()
    .from(Task.class)
    .where(getPrimaryConditionClause(model))
    .hasData(wrapper);
  }

  @Override
  public final OperatorGroup getPrimaryConditionClause(Task model) {
    OperatorGroup clause = OperatorGroup.clause();
    clause.and(id.eq(model.getId()));
    return clause;
  }

  @Override
  public final boolean save(Task model) {
    boolean successful = super.save(model);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.saveAll(model.savePermissions());
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.saveAll(model.saveChecklists());
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.saveAll(model.saveMarkers());
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.saveAll(model.saveAttachments());
    }
    return successful;
  }

  @Override
  public final long insert(Task model) {
    long rowId = super.insert(model);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.insertAll(model.savePermissions());
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.insertAll(model.saveChecklists());
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.insertAll(model.saveMarkers());
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.insertAll(model.saveAttachments());
    }
    return rowId;
  }

  @Override
  public final boolean update(Task model) {
    boolean successful = super.update(model);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.updateAll(model.savePermissions());
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.updateAll(model.saveChecklists());
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.updateAll(model.saveMarkers());
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.updateAll(model.saveAttachments());
    }
    return successful;
  }

  @Override
  public final boolean save(Task model, DatabaseWrapper wrapper) {
    boolean successful = super.save(model, wrapper);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.saveAll(model.savePermissions(), wrapper);
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.saveAll(model.saveChecklists(), wrapper);
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.saveAll(model.saveMarkers(), wrapper);
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.saveAll(model.saveAttachments(), wrapper);
    }
    return successful;
  }

  @Override
  public final long insert(Task model, DatabaseWrapper wrapper) {
    long rowId = super.insert(model, wrapper);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.insertAll(model.savePermissions(), wrapper);
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.insertAll(model.saveChecklists(), wrapper);
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.insertAll(model.saveMarkers(), wrapper);
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.insertAll(model.saveAttachments(), wrapper);
    }
    return rowId;
  }

  @Override
  public final boolean update(Task model, DatabaseWrapper wrapper) {
    boolean successful = super.update(model, wrapper);
    if (model.savePermissions() != null) {
      ModelAdapter<Permission> adapter = FlowManager.getModelAdapter(Permission.class);
      adapter.updateAll(model.savePermissions(), wrapper);
    }
    if (model.saveChecklists() != null) {
      ModelAdapter<Checklist> adapter = FlowManager.getModelAdapter(Checklist.class);
      adapter.updateAll(model.saveChecklists(), wrapper);
    }
    if (model.saveMarkers() != null) {
      ModelAdapter<Marker> adapter = FlowManager.getModelAdapter(Marker.class);
      adapter.updateAll(model.saveMarkers(), wrapper);
    }
    if (model.saveAttachments() != null) {
      ModelAdapter<Attachment> adapter = FlowManager.getModelAdapter(Attachment.class);
      adapter.updateAll(model.saveAttachments(), wrapper);
    }
    return successful;
  }
}

I managed to insert other columns in other tables and I didn't get the same error. For an example, the migration script I ran in my DataBase to insert the column "categoryId" was similar to this one:

@Database(name = ConstructDB.NAME, version = ConstructDB.VERSION)
public class ConstructDB {
  public static final String NAME = "construct_v3";
  public static final int VERSION = 22;

  @Migration(version = 21, database = ConstructDB.class)
  public static class Migration21 extends AlterTableMigration<UserProject> {
    public Migration21(Class<UserProject> table) {
      super(table);
    }

    @Override
    public void onPreMigrate() {
      super.onPreMigrate();
      addColumn(SQLiteType.TEXT, "load");
    }
  }
}

This is the LogCat I received through CrashLytics:

Fatal Exception: android.database.sqlite.SQLiteException: no such column: categoryId (code 1): , while compiling: SELECT `id`,`project_id`,`title`,`description`,`collection_id`,`priority`,`created_at`,`created_by`,`updated_at`,`due_date`,`completed_at`,`completed_by`,`categoryId`,`feed_count`,`R`.`read_count` FROM `Task` AS `T` LEFT OUTER JOIN `TaskRead` AS `R` ON `id`=`task_id` WHERE (`project_id`='5716f387d07c5a887cf97c4b' AND `completed_at` IS NULL ) ORDER BY `due_date` ASC, `priority` DESC, `created_at` ASC LIMIT 2147483647
       at android.database.sqlite.SQLiteConnection.nativePrepareStatement(SQLiteConnection.java)
       at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:898)
       at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:509)
       at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
       at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
       at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
       at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
       at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1346)
       at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1285)
       at com.raizlabs.android.dbflow.structure.database.AndroidDatabase.rawQuery(AndroidDatabase.java:62)
       at com.raizlabs.android.dbflow.sql.queriable.ModelLoader.load(ModelLoader.java:59)
       at com.raizlabs.android.dbflow.sql.queriable.ListModelLoader.load(ListModelLoader.java:44)
       at com.raizlabs.android.dbflow.sql.queriable.ListModelLoader.load(ListModelLoader.java:15)
       at com.raizlabs.android.dbflow.sql.queriable.ModelLoader.load(ModelLoader.java:53)
       at com.raizlabs.android.dbflow.sql.queriable.ListModelLoader.load(ListModelLoader.java:37)
       at com.raizlabs.android.dbflow.sql.queriable.ListModelLoader.load(ListModelLoader.java:15)
       at com.raizlabs.android.dbflow.sql.queriable.ModelLoader.load(ModelLoader.java:36)
       at com.raizlabs.android.dbflow.sql.queriable.ListModelLoader.load(ListModelLoader.java:25)
       at com.raizlabs.android.dbflow.sql.language.BaseModelQueriable.queryList(BaseModelQueriable.java:61)
       at com.raizlabs.android.dbflow.sql.language.Where.queryList(Where.java:236)
       at com.construct.v2.db.dao.TaskDao.read(TaskDao.java:39)
       at com.construct.v2.providers.TaskProvider.readCached(TaskProvider.java:62)
       at com.construct.v2.providers.TaskProvider.read(TaskProvider.java:54)
       at com.construct.v2.viewmodel.entities.tasks.TasksViewModel.load(TasksViewModel.java:37)
       at com.construct.v2.viewmodel.entities.AbstractEntitiesViewModel.subscribe(AbstractEntitiesViewModel.java:76)
       at com.construct.v2.fragments.entities.TasksFragment.onViewCreated(TasksFragment.java:82)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1314)
       at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
       at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
       at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:758)
       at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2363)
       at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149)
       at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103)
       at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2013)
       at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710)
       at android.os.Handler.handleCallback(Handler.java:815)
       at android.os.Handler.dispatchMessage(Handler.java:104)
       at android.os.Looper.loop(Looper.java:194)
       at android.app.ActivityThread.main(ActivityThread.java:5624)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
4

1 回答 1

0

在您的设备上首次安装应用程序后,将创建数据库,如果您更改数据库(更改列、添加列或添加表......)并且您的设备上有以前版本的应用程序,安装新版本后数据库不会改变。因此,如果您想更改数据库,则需要卸载以前版本的应用程序。如果您已将您的应用发布给您的用户,并且您希望您的用户不会丢失以前的版本数据,您必须迁移您的数据库。

于 2018-05-29T06:47:39.420 回答