Android Room Persistence Library:处理错误

时间:2017-08-22 08:18:40

标签: android android-room

我正在试图弄清楚如何处理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是否发生了。如果是,我抛出异常。 但这是处理错误的好方法还是有更好的方法?

1 个答案:

答案 0 :(得分:0)

  

如果是,我抛出异常。但这是一种很好的处理方式   错误还是有更好的方法?

这在很大程度上取决于您要做什么以及基础架构。

例如,如果您只想知道插入是否成功,则(假设您未使用外键)然后在 @Insert中使用 onConflict (可选)以及使用从插入中返回的值(即 rowid 作为长整数)可以毫无例外地产生相同的结果。

例如,考虑以下实体:-

@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 为空或现有 item_id

的插入

使用:-

中的任何一个
@Insert
void insertItem(Item item);

@Insert
void insertItems(Item... items);
如果尝试插入item_id为null或现有item_id的行,则

将导致异常

但是,使用

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

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

不会导致异常,因为基础SQL有效地是INSERT或IGNORE,此外,将返回行号(对于后者),然后可以对其进行查询。

首先,如果返回的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")}
        )
.........
  

但这是处理错误的好方法还是有更好的方法   方式吗?

由于答案是基于意见的,因此无法真正给出答案,而是经常有使用异常处理的替代方法。已经显示了一些。