A biblioteca de persistência Room do Android graciosamente inclui as anotações @Insert e @Update que funcionam para objetos ou coleções. No entanto, tenho um caso de uso (notificações push contendo um modelo) que exigiria um UPSERT, pois os dados podem ou não existir no banco de dados.
O Sqlite não tem upsert nativamente e as soluções alternativas são descritas nesta pergunta do SO . Dadas as soluções lá, como aplicá-las à Room?
Para ser mais específico, como posso implementar uma inserção ou atualização na Room que não quebraria nenhuma restrição de chave estrangeira? Usar insert com onConflict = REPLACE fará com que o onDelete de qualquer chave estrangeira para aquela linha seja chamada. No meu caso, onDelete causa uma cascata e a reinserção de uma linha fará com que as linhas em outras tabelas com a chave estrangeira sejam excluídas. Este NÃO é o comportamento pretendido.
Para uma maneira mais elegante de fazer isso, sugiro duas opções:
Verificando o valor de retorno da
insert
operação comIGNORE
as aOnConflictStrategy
(se for igual a -1, significa que a linha não foi inserida):Lidando com exceção de
insert
operaçãoFAIL
comoOnConflictStrategy
:fonte
Não consegui encontrar uma consulta SQLite que pudesse inserir ou atualizar sem causar alterações indesejadas em minha chave estrangeira, então, em vez disso, optei por inserir primeiro, ignorando os conflitos se eles ocorressem e atualizando imediatamente depois, novamente ignorando os conflitos.
Os métodos de inserção e atualização são protegidos para que as classes externas vejam e usem apenas o método upsert. Lembre-se de que este não é um verdadeiro upsert, pois se algum dos POJOS do MyEntity tiver campos nulos, eles substituirão o que pode estar atualmente no banco de dados. Esta não é uma advertência para mim, mas pode ser para sua aplicação.
fonte
upsert
método com a@Transaction
anotaçãoSe a tabela tiver mais de uma coluna, você pode usar
para substituir uma linha.
Referência - Vá para dicas Android Room Codelab
fonte
deferred = true
na entidade com a chave estrangeira.Este é o código em Kotlin:
}
fonte
null values
onde não quero atualizar com nulo, mas reter o valor antigo. ?Apenas uma atualização de como fazer isso com Kotlin retendo dados do modelo (talvez para usá-lo em um contador como no exemplo):
Você também pode usar @Transaction e variável de construtor de banco de dados para transações mais complexas usando database.openHelper.writableDatabase.execSQL ("SQL STATEMENT")
fonte
Outra abordagem que posso pensar é obter a entidade por meio do DAO por consulta e, em seguida, executar as atualizações desejadas. Isso pode ser menos eficiente em comparação com as outras soluções neste segmento em termos de tempo de execução por ter que recuperar a entidade completa, mas permite muito mais flexibilidade em termos de operações permitidas, como em quais campos / variáveis atualizar.
Por exemplo :
fonte
Deve ser possível com este tipo de declaração:
fonte
ON CONFLICT UPDATE SET a = 1, b = 2
não é compatível comRoom
@Query
anotações.