Подтвердить что ты не робот

Библиотека сохранения объектов Android: устранение ошибок

Я пытаюсь выяснить, как обрабатывать ошибки в Room. У меня есть следующий интерактор, который вставляет задачу в базу данных:

TaskInteractor.java

public class TaskInteractor extends AbstractInteractor implements TaskContract.Interactor {

    final TaskRepository mRepository;

    interface Callback {
        void onSuccess();
        void onFailure(Throwable t);
    }

    @Inject
    public TaskInteractor(WorkerThread workerThread,
                             MainThread mainThread,
                             TaskRepository repository) {
        super(workerThread, mainThread);
        this.mRepository = repository;
    }

    @Override
    public void insertTask(final Task task, final Callback callback)
            throws SQLiteException {
        mWorkerThread.get().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    mRepository.insertTask(task);
                } catch (SQLiteException exeption) {
                    Timber.e("Insertion failed. Exception: " + exeption.getMessage());
                    callback.onFailure(exeption);
                    throw exeption;
                }
                Timber.d("Insertion succeeded.");
                callback.onSuccess();
            }
        });
    }
}

В insertTask я использую блок try-catch, чтобы проверить, произошло SQLiteException событие SQLiteException. Если это так, я делаю исключение. Но разве это хороший способ обработки ошибок или, может быть, лучший способ?

4b9b3361

Ответ 1

Если это произойдет, я брошу исключение. Но это хороший способ обработки ошибок или, может быть, есть лучший способ?

Это очень сильно зависит от того, что вы хотите сделать, и от базовой схемы.

Например, если все, что вы хотите знать, это то, была ли вставка успешной или нет, тогда (при условии, что вы не используете Внешние ключи), тогда используйте onConflict в @Insert, опционально, вместе с использованием значения, возвращенного из вставки (т.е. rowid ( long) может дать тот же результат без исключения.

Например, рассмотрим следующую сущность:

@Entity(tableName = "item")
public class Item {
    @PrimaryKey
    @NonNull
    @ColumnInfo(name = "item_id")
    private String item_id;

    @ColumnInfo(name = "description")
    private String description;

    @ColumnInfo(name = "price")
    private double price;

    ...........
}

Единственная вставка, которая не должна работать, это вставка, в которой item_id имеет значение null или существующий item_id.

Используя любой из: -

@Insert
void insertItem(Item item);

@Insert
void insertItems(Item... items);

приведет к исключению, если будет сделана попытка вставить строку, где item_id равен нулю или существующий item_id

Однако, используя

@Insert(onConflict = OnConflictStrategy.IGNORE)
long insertItem(Item item);

@Insert(onConflict = OnConflictStrategy.IGNORE)
long[] insertItems(Item... items);

не приведет к исключению, так как базовый SQL фактически является INSERT OR IGNORE, кроме того, будут возвращены rowid или rowid (для последнего), которые затем могут быть опрошены.

Во-первых, если возвращенный идентификатор строки меньше 1, то строка не была вставлена.

Во втором случае, когда вы вставляете строки на основе списка объектов, вы можете проверить каждый элемент возвращаемого массива, чтобы увидеть, какие были, а какие не были вставлены. Поэтому во втором примере не будет необходимости обрабатывать исключения.

Тем не менее, если задействованы внешние ключи, исключения не могут быть обнаружены. Их можно предотвратить, проверив, существует ли родительский столбец (перед вставкой)

Еще одним осложнением с внешними ключами может быть обработка обновлений/удалений родительского элемента. Их можно уменьшить, используя onUpdate/onDelete (часто путем указания CASCADE), например:

@Entity(tableName = "invoice",
        foreignKeys = {
        @ForeignKey(
                entity = Item.class,
                parentColumns = "item_id",childColumns = "item_reference",onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE)},
        indices = {@Index(value = "item_reference")}
        )
.........

Но это хороший способ обработки ошибок или, может быть, есть лучший способ?

Ответ на самом деле не может быть дан, так как ответ будет основываться на мнении, а часто есть альтернативы использованию обработки исключений. Некоторые из них были показаны.