android - Realm :未为字段定义索引

标签 android realm

我正在编写一个 RealmMigration,在此期间发生了几次不同的错误之后,我想我终于明白了,但现在我得到了 io.realm.exceptions.RealmMigrationNeededException: Index not defined for field 'primaryKey'。

我看到一些关于需要使用 table.addSearchIndex() 的信息,但即使在为我的每个表添加它之后我仍然遇到异常。

这是我的迁移类。

迁移.java

public class Migration implements RealmMigration {

@Override
public long execute(Realm realm, long version) {
    Timber.i("Current database version: " + version);

    /**
     * Version 1:
     *      Task:
     *          Remove boolean field completed
     *          Remove Date field completedDate
     *      Transaction:
     *          Add int field type
     */
    if (version == 0) {
        // Transaction
        Table transactionTable = realm.getTable(Transaction.class);
        transactionTable.addColumn(ColumnType.INTEGER, "type");
        long transactionPrimaryKeyIndex = getIndexForProperty(transactionTable, "primaryKey");
        long transactionTitleIndex = getIndexForProperty(transactionTable, "title");
        long transactionPointsIndex = getIndexForProperty(transactionTable, "points");
        long transactionDateIndex = getIndexForProperty(transactionTable, "date");
        long transactionTypeIndex = getIndexForProperty(transactionTable, "type");

        for (int i = 0; i < transactionTable.size(); i++) {
            // Until now the only possible transaction was reward
            transactionTable.setLong(transactionTypeIndex, i, Transaction.TYPE_REWARD);
        }

        // Task
        Table taskTable = realm.getTable(Task.class);

        // Go through and create Transactions for each completed Task
        long taskPrimaryKeyIndex = getIndexForProperty(taskTable, "primaryKey");
        long taskCompletedIndex = getIndexForProperty(taskTable, "completed");
        long taskCompletedDateIndex = getIndexForProperty(taskTable, "completedDate");
        long taskTitleIndex = getIndexForProperty(taskTable, "title");
        long taskPointsIndex = getIndexForProperty(taskTable, "points");


        for (int i = 0; i < taskTable.size(); i++) {
            if (taskTable.getBoolean(taskCompletedIndex, i)) {
                transactionTable.addEmptyRowWithPrimaryKey(transactionTable.getLong(transactionPrimaryKeyIndex, transactionTable.size() - 1) + 1);
                long j = transactionTable.size() - 1; // The new row

                transactionTable.setString(transactionTitleIndex, j, taskTable.getString(taskTitleIndex, i));
                transactionTable.setLong(transactionPointsIndex, j, taskTable.getLong(taskPointsIndex, i));
                transactionTable.setDate(transactionDateIndex, j, taskTable.getDate(taskCompletedDateIndex, i));
                transactionTable.setLong(transactionTypeIndex, j, Transaction.TYPE_TASK);
            }
        }

        // Finally, remove the columns we don't need any more
        taskTable.removeColumn(getIndexForProperty(taskTable, "completed"));
        taskTable.removeColumn(getIndexForProperty(taskTable, "completedDate"));

        // https://realm.io/news/realm-java-0.82.0/
        taskTable.addSearchIndex(taskPrimaryKeyIndex);
        transactionTable.addSearchIndex(transactionPrimaryKeyIndex);

        Table reminderTable = realm.getTable(Reminder.class);
        Table rewardTable = realm.getTable(Reward.class);
        reminderTable.addSearchIndex(getIndexForProperty(reminderTable, "primaryKey"));
        rewardTable.add(getIndexForProperty(rewardTable, "primaryKey"));

        version++;
    }

    return version;
}

private long getIndexForProperty(Table table, String name) {
    for (int i = 0; i < table.getColumnCount(); i++) {
        if (table.getColumnName(i).equals(name)) {
            return i;
        }
    }
    return -1;
}

任务.java

public class Task extends RealmObject {
    @PrimaryKey
    private long primaryKey;
    private String title;
    private String description;
    private int points;
    private boolean hasReminders;
    private RealmList<Reminder> reminders;

    public static long getNextPrimaryKey(Realm realm) {
        RealmResults<Task> tasks = realm.where(Task.class).findAllSorted("primaryKey");
        if (tasks.size() == 0) return 0;
        return tasks.last().getPrimaryKey() + 1;
    }

    // Getters and setters
}

事务.java

public class Transaction extends RealmObject {
    public static final int TYPE_TASK = 0;
    public static final int TYPE_REWARD = 1;

    @PrimaryKey
    private long primaryKey;
    private String title;
    private int points;
    private Date date;
    private int type;

    public static long getNextPrimaryKey(Realm realm) {
        if (realm != null) {
            RealmResults<Transaction> transactions = realm.where(Transaction.class).findAllSorted("primaryKey");
            if (transactions.size() == 0) return 0;
                return transactions.last().getPrimaryKey() + 1;
            } else {
                return 0;
            }
        }
    }

    // Getters and setters
}

最佳答案

这是因为您在添加索引之前删除了任务表中的两列。这意味着您在开始时计算的索引不再有效。

关于android - Realm :未为字段定义索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32720604/

相关文章:

android - 如何使 SQLite 选择查询更快

android - 带有 PendingIntent 的 RequestLocationUpdates 永远不会触发

android - 访问标准安卓设置 : PIN code of the SIM card

java - Android下的测试境界

ios - 如何在 Realm 数组的特定索引处插入对象?

Android Volley - 取消 Base Adapter 中的 NetworkImageView 请求

ios - 无法将类型 'Option' 的值转换为预期的参数类型 '@noescape (Option) throws -> Bool'

ios - 一对一关系 Realm 与新的实时反向关系

java - Realm DB 在 Android 中变得疯狂

android - 使 AsyncTask 静态(有问题,提供代码)