2
respostas

Tratamento de erro nas funções Room

Olá pessoal, tudo bom ?

Fiz a implementação corretamente do Room funcionou certinho nos meus testes, mas ao fazer a adição com as sincronias ocorreu o seguinte erro:

Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787 SQLITE_CONSTRAINT_FOREIGNKEY[787])
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:995)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
        at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:64)
        at br.com.sat.cronos.database.dao.tarefa.TarefaDAO_Impl.inserir(TarefaDAO_Impl.java:142)
        at br.com.sat.cronos.database.dao.tarefa.TarefaDAO_Impl.inserir(TarefaDAO_Impl.java:17)
        at br.com.sat.cronos.repository.tarefa.TarefaRepository$salvar$1.invoke(TarefaRepository.kt:37)
        at br.com.sat.cronos.repository.tarefa.TarefaRepository$salvar$1.invoke(TarefaRepository.kt:11)
        at br.com.sat.cronos.asynctask.BaseAsyncTask.doInBackground(BaseAsyncTask.kt:12)
        at br.com.sat.cronos.asynctask.BaseAsyncTask.doInBackground(BaseAsyncTask.kt:7)
        at android.os.AsyncTask$2.call(AsyncTask.java:333)

Acabei criando um BaseDao que recebe um generic para que eu possa usar de forma dinâmica:

package br.com.sat.cronos.database.dao

import androidx.annotation.WorkerThread
import androidx.room.*

/**
 * Classe base de DAO
 * @author Gustavo Pinto
 * @version 1.0
 * @since 1.0
 *
 */
@Dao
interface BaseDAO<T> {

    /**
     * Insere um objeto no banco de dados
     *
     * @param obj
     */
    @Insert
    fun inserir(obj: T)

    /**
     * Insere um array de objetos no banco de dados
     *
     * @param list
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    @WorkerThread
    fun inserir(list: List<T>)

    /**
     * Atualizar um objeto no banco de dados
     *
     * @param obj
     */
    @Update
    fun atualizar(obj: T)

    /**
     * Remove um objeto do banco de dados
     *
     * @param obj
     */
    @Delete
    fun remover(obj: T)

}

E faço a chamada da seguinte forma ao inserir:

 fun salvar(ta: Tarefa, callback: (Unit?) -> Unit) {
        try {
            BaseAsyncTask(executar = {
                if (buscaPorId(ta.id) == null) {
                    dao?.inserir(ta)
                } else {
                    dao?.atualizar(ta)
                }
            }, finaliza = callback)
                .execute()
        } catch (erro: Exception) {
            CrashlyticsUtil.enviaErro(context, TAG, erro)
        }
    }

Assim gostaria de saber como eu poderia fazer para tratar esse erro para não crashar a aplicação e enviar para a função que chamou a função de inserir do BaseDao o erro para conseguir enviar para a minha classe CrashlyticsUtil.

2 respostas

A primeira linha do erro diz: "FOREIGN KEY constraint failed" indicando que esta ocorrendo erro de chave estrangeira: esta tentando gravar determinado valor em campo que faz relacionamento com outra tabela, sendo que esse valor não existe nessa outra tabela.

Olá Elizângela,

Sim, o erro eu forcei para acontecer, pq quero tratar esse erro para que isso não crashe a aplicação e feche enquanto o usuário esteja usando. Quero fazer o tratamento para que eu consiga pegar o erro e o objeto para documentar e enviar para meu painel de falha.