Não vamos supor que tenho um banco de dados simples do Room:
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Agora, estou adicionando uma nova entidade: Pet
e aumentando a versão para 2:
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Claro, o Room lança uma exceção: java.lang.IllegalStateException: A migration from 1 to 2 is necessary.
Supondo que eu não mudei de User
classe (portanto, todos os dados estão seguros), tenho que fornecer uma migração que apenas cria uma nova tabela. Então, estou procurando por classes geradas pelo Room, procurando por consulta gerada para criar minha nova tabela, copiando e colando na migração:
final Migration MIGRATION_1_2 =
new Migration(1, 2) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `Pet` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))");
}
};
No entanto, acho inconveniente fazê-lo manualmente. Existe uma maneira de dizer ao Room: não estou tocando em nenhuma tabela existente, então os dados estão seguros. Por favor, crie a migração para mim?
java
android
database-migration
android-room
Piotr Aleksander Chmielowski
fonte
fonte
Respostas:
Quarto se não tiver um bom sistema de migração, pelo menos não até
2.1.0-alpha03
.Portanto, até que tenhamos um sistema de migração melhor, existem algumas soluções alternativas para facilitar as migrações na sala.
Como não existe um método como
@Database(createNewTables = true)
ouMigrationSystem.createTable(User::class)
, que deveria haver um ou outro, a única maneira possível é executandodentro do seu
migrate
método.Para obter o script SQL acima , você tem 4 maneiras
1. Escreva sozinho
Basicamente, você deve escrever o script acima que irá corresponder ao script gerado pela Room. Esse caminho é possível, não viável. (Considere que você tem 50 campos)
2. Esquema de exportação
Se você incluir
exportSchema = true
em sua@Database
anotação, a Room irá gerar o esquema do banco de dados dentro de / schemas da pasta do seu projeto. O uso éCertifique-se de incluir as linhas abaixo no
build.grade
módulo do seu aplicativoAo executar ou construir o projeto, você obterá um arquivo JSON
2.json
, que contém todas as consultas no banco de dados do Room.Portanto, você pode incluir o acima
createSql
dentro de seumigrate
método.3. Obtenha a consulta de AppDatabase_Impl
Se você não quiser exportar o esquema, você ainda pode obter a consulta executando ou construindo o projeto que irá gerar o
AppDatabase_Impl.java
arquivo. e dentro do arquivo especificado você pode ter.Dentro do
createAllTables
método, haverá os scripts de criação de todas as entidades. Você pode obtê-lo e incluí-lo em seumigrate
método.4. Processamento de anotações.
Como você pode imaginar, o Room gera todos os itens mencionados acima
schema
, eAppDatabase_Impl
arquivos dentro do tempo de compilação e com processamento de anotação que você adiciona comIsso significa que você também pode fazer o mesmo e criar sua própria biblioteca de processamento de anotações que gera todas as consultas de criação necessárias para você.
A ideia é fazer uma biblioteca de processamento de anotações para anotações de Room
@Entity
e@Database
. Pegue uma classe com anotações,@Entity
por exemplo. Estas são as etapas que você terá que seguirStringBuilder
e anexe "CRIAR TABELA SE NÃO EXISTIR"class.simplename
ou portableName
campo de@Entity
. Adicione ao seuStringBuilder
@ColumnInfo
anotação. Para cada campo, você deve adicionar oid INTEGER NOT NULL
estilo de uma coluna ao seuStringBuilder
.@PrimaryKey
ForeignKey
eIndices
se existir.Então, você pode usá-lo como
Eu fiz uma biblioteca para mim que você pode conferir e até mesmo usar em seu projeto. Observe que a biblioteca que fiz não está cheia e apenas atende aos meus requisitos para a criação de tabelas.
RoomExtension para uma melhor migração
Aplicativo que usa RoomExtension
Espero que tenha sido útil.
ATUALIZAR
No momento em que escrevi esta resposta, a versão da sala era
2.1.0-alpha03
e quando enviei um e-mail aos desenvolvedores, recebi uma resposta deInfelizmente, ainda não temos um sistema de migração melhor.
fonte
A Room não oferece suporte à criação automática de tabelas sem perda de dados.
É obrigatório escrever a migração. Caso contrário, ele apagará todos os dados e criará a nova estrutura da tabela.
fonte
Você pode fazer desta forma-
O restante será o mesmo que você mencionou acima-
Referência - para mais
fonte
Você pode adicionar o seguinte comando gradle ao defaultConfig em seu app.gradle:
Quando você o executa, ele compila uma lista de nomes de tabela com suas instruções CREATE TABLE relevantes, da qual você pode simplesmente copiar e colar em seus objetos de migração. Você pode ter que alterar os nomes das tabelas.
Por exemplo, isso é do meu esquema gerado:
E então eu copio e colo a instrução createSql e altero '$ {TABLE_NAME}' para 'assets' o nome da tabela, e voila as instruções de criação de Room gerados automaticamente.
fonte
Nesse caso, você não precisa fazer uma migração, você pode chamar .fallbackToDestructiveMigration () ao criar uma instância do banco de dados.
Exemplo:
E não se esqueça de mudar a versão do banco de dados.
fonte
Talvez neste caso (se você apenas criou uma nova tabela sem alterar as outras) você possa fazer isso sem criar nenhuma migração?
fonte