5
respostas

Algum problema com a Migration

App quebrou. Por fim copiei todos os arquivos do programa do professor e ainda assim não deu certo

Logcat devolve isso:

FATAL EXCEPTION: main Process: xavier.f, PID: 9234 java.lang.RuntimeException: Unable to resume activity {xavier.f/xavier.f.ui.activity.ListaAlunosActivity}: java.lang.IllegalStateException: Migration didn't properly handle: Telefone(xavier.f.model.Telefone). Expected: TableInfo{name='Telefone', columns={tipo=Column{name='tipo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, alunoId=Column{name='alunoId', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, numero=Column{name='numero', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[ForeignKey{referenceTable='Aluno', onDelete='CASCADE +', onUpdate='CASCADE', columnNames=[alunoId], referenceColumnNames=[id]}], indices=[]} Found: TableInfo{name='Telefone', columns={id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='undefined'}, numero=Column{name='numero', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, tipo=Column{name='tipo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='undefined'}, alunoId=Column{name='alunoId', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='undefined'}}, foreignKeys=[], indices=[]} at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5378) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5444) at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8757) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

    Alguém tem alguma idéia do que seja?
                                                                                                    
                                                                        
5 respostas

Já reparei que as tabelas não batem Expected x Found

É algum problema relacionado a classe Telefone

import static androidx.room.ForeignKey.*;

import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;

@Entity(foreignKeys = @ForeignKey(entity = Aluno.class, parentColumns = "id", childColumns = "alunoId", onUpdate = CASCADE, onDelete = CASCADE))
public class Telefone {

    @PrimaryKey(autoGenerate = true)
    private int id;
    private String numero;
    private TipoTelefone tipo;
    private int alunoId;

    public int getAlunoId() {
        return alunoId;
    }

    public void setAlunoId(int alunoId) {
        this.alunoId = alunoId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    public TipoTelefone getTipo() {
        return tipo;
    }

    public void setTipo(TipoTelefone tipo) {
        this.tipo = tipo;
    }

}

Segue a migration

import static xavier.f.model.TipoTelefone.FIXO;

import androidx.annotation.NonNull;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;

import xavier.f.model.TipoTelefone;

class AgendaMigrations {

    private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE Aluno ADD COLUMN sobrenome TEXT");
        }
    };
    private static final Migration MIGRATION_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            // Criar nova tabela com as informações desejadas
            database.execSQL("CREATE TABLE IF NOT EXISTS `Aluno_novo` " +
                    "(`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                    "`nome` TEXT, " +
                    "`telefone` TEXT, " +
                    "`email` TEXT)");

            // Copiar dados da tabela antiga para a nova
            database.execSQL("INSERT INTO Aluno_novo (id, nome, telefone, email) " +
                    "SELECT id, nome, telefone, email FROM Aluno");

            // Remove tabela antiga
            database.execSQL("DROP TABLE Aluno");

            // Renomear a tabela nova com o nome da tabela antiga
            database.execSQL("ALTER TABLE Aluno_novo RENAME TO Aluno");
        }
    };
    private static final Migration MIGRATION_3_4 = new Migration(3, 4) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE Aluno ADD COLUMN momentoDeCadastro INTEGER");
        }
    };
    private static final Migration MIGRATION_4_5 = new Migration(4, 5) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("CREATE TABLE IF NOT EXISTS `Aluno_novo` (" +
                    "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                    "`nome` TEXT, " +
                    "`telefoneFixo` TEXT, " +
                    "`email` TEXT, " +
                    "`momentoDeCadastro` INTEGER, " +
                    "`telefoneCelular` TEXT)");

            database.execSQL("INSERT INTO Aluno_novo (id, nome, telefoneFixo, email, momentoDeCadastro) " +
                    "SELECT id, nome, telefone, email, momentoDeCadastro FROM Aluno");

            database.execSQL("DROP TABLE Aluno");

            database.execSQL("ALTER TABLE Aluno_novo RENAME TO Aluno");
        }
    };
    private static final Migration MIGRATION_5_6 = new Migration(5, 6) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("CREATE TABLE IF NOT EXISTS `Aluno_novo` (" +
                    "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                    "`nome` TEXT, " +
                    "`email` TEXT, " +
                    "`momentoDeCadastro` INTEGER)");

            database.execSQL("INSERT INTO Aluno_novo (id, nome, email, momentoDeCadastro) " +
                    "SELECT id, nome, email, momentoDeCadastro FROM Aluno");

            database.execSQL("CREATE TABLE IF NOT EXISTS `Telefone` (" +
                    "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                    "`numero` TEXT, " +
                    "`tipo` TEXT, " +
                    "`alunoId` INTEGER NOT NULL)");

            database.execSQL("INSERT INTO Telefone (numero, alunoId) " +
                    "SELECT telefoneFixo, id FROM Aluno");

            database.execSQL("UPDATE Telefone SET tipo = ?", new TipoTelefone[] {FIXO});

            database.execSQL("DROP TABLE Aluno");

            database.execSQL("ALTER TABLE Aluno_novo RENAME TO Aluno");
        }
    };
    static final Migration[] TODAS_MIGRATIONS = {MIGRATION_1_2, MIGRATION_2_3,
            MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6};

}

Por fim, não achando solução refiz todo o projeto

Ainda sem sucesso

O compilador não deixa eu por a ForeignKey em cima do atributo e quando declaro direto em @Entity o buil me retorna esse aviso:

Task :app:compileDebugJavaWithJavac C:\Users\55479\AndroidStudioProjects\Agenda2\app\src\main\java\xavier\fernando\agenda2\model\Telefone.java:14: warning: alunoId column references a foreign key but it is not part of an index. This may trigger full table scans whenever parent table is modified so you are highly advised to create an index that covers this column. public class Telefone { ^ Note: C:\Users\55479\AndroidStudioProjects\Agenda2\app\src\main\java\xavier\fernando\agenda2\ui\activity\FormularioAlunoActivity.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. 1 warning

Ola!

O logcat que você forneceu indica um problema durante a migração do banco de dados, especialmente relacionado à entidade 'Telefone'. O erro destaca uma inconsistência entre a estrutura esperada e a encontrada. Vamos simplificar isso:

O sistema esperava que a tabela 'Telefone' tivesse uma ordem específica de colunas durante a migração, mas a ordem real das colunas encontradas não correspondia a essa expectativa.

Se olharmos para o código da sua entidade 'Telefone', podemos notar que a migração está tentando criar uma nova tabela 'Telefone' e transferir dados da tabela antiga para a nova estrutura. O problema pode estar na ordem das colunas ao criar a nova tabela.

Sugiro verificar a migração correspondente (MIGRATION_5_6) e garantir que a ordem das colunas na criação da tabela 'Telefone' esteja correta. Certifique-se de que a ordem seja: id, numero, tipo, alunoId.

Além disso, notei que o Room está indicando um aviso sobre a ForeignKey, sugerindo que o atributo 'alunoId' na tabela 'Telefone' não faz parte de um índice. Isso pode causar lentidão nas consultas sempre que a tabela pai for modificada. Para corrigir isso, adicione um índice ao 'alunoId' na tabela 'Telefone'.