[RESOLVIDO] Como implemento a inserção do ID de uma classe na chave estrangeira de outra - SQLite?

Boa noite.

Tenho um Banco de dados no SQLite que tem 11 tabelas, mas as principais são Professor, Aluno, ambos recebem a chave estrangeira de Endereco, Endereco, Turno, Turma, Disciplina, Matricula e Ano Letivo. A cardinalidade delas é N:N em todas, daí já viu neh… Fiz um diagrama, mas gostaria de opiniões se ele está certo ou não. Segue abaixo:

Quero saber como preenche as COLULAS das FKs.

Por favor, não fala em INSERT INTO… que não é o que procuro. Eu quero saber como preencho os inserts, por exemplo:

no onCreate:

banco.execSQL("CREATE TABLE " + TABELA_ENDERECO +
	  "(" + ID_ENDERECO + " INTEGER PRIMARY KEY AUTOINCREMENT," +
	  PAIS_ENDERECO + " TEXT," +
	  ESTADO_ENDERECO + " TEXT," +
	  CIDADE_ENDERECO + " TEXT," +
	  BAIRRO_ENDERECO + " TEXT," +
	  RUA_ENDERECO + " TEXT," +
	  NUMERO_ENDERECO + " TEXT," +
	  COMPLEMENTO_ENDERECO + " TEXT," +
	  CEP_ENDERECO + " TEXT)");

// TABELA_PROFESSOR
banco.execSQL("CREATE TABLE " + TABELA_PROFESSOR +
	  "(" + ID_PROF + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
	  NOME_PROFESSOR + " TEXT," +
	  CPF_PROFESSOR + " TEXT," +
	  FOTO_PROFESSOR + " BLOB," +
	  HORARIO_CADASTRO_PROFESSOR + " TEXT," +
	  FK_ID_PROF_ENDERECO + " INTEGER," +
	  "FOREIGN KEY (" + FK_ID_PROF_ENDERECO + ") REFERENCES " + TABELA_ENDERECO + (ID_ENDERECO) +")");

// TABELA_ALUNO
banco.execSQL("CREATE TABLE " + TABELA_ALUNO +
	  "(" + ID_ALUNO + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
	  NOME_ALUNO + " TEXT," +
	  CPF_ALUNO + " TEXT," +
	  FOTO_ALUNO + " BLOB," +
	  HORARIO_CADASTRO_ALUNO + " TEXT," +
	  FK_ID_ALUNO_ENDERECO + " INTEGER," +
	  "FOREIGN KEY (" + FK_ID_ALUNO_ENDERECO + ") REFERENCES " + TABELA_ENDERECO + (ID_ENDERECO) + ")");

Nos métodos de inserção:

 public boolean inserirEnderecoBanco(String estado, String cidade, String bairro, String rua, String num, String compl, String pais, String cep){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(PAIS_ENDERECO, pais);
      contentValues.put(ESTADO_ENDERECO, estado);
      contentValues.put(CIDADE_ENDERECO, cidade);
      contentValues.put(BAIRRO_ENDERECO, bairro);
      contentValues.put(RUA_ENDERECO, rua);
      contentValues.put(NUMERO_ENDERECO, num);
      contentValues.put(COMPLEMENTO_ENDERECO, compl);
      contentValues.put(CEP_ENDERECO, cep);

      long resultado = banco.insert(TABELA_ENDERECO, null, contentValues);

      if(resultado == -1){
           return false;
      }
      else{
           return true;
      }
 }

 public boolean inserirProfessorBanco(String nome, String cpf, byte[] foto, String horarioCadastro){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(NOME_PROFESSOR, nome);
      contentValues.put(CPF_PROFESSOR, cpf);
      contentValues.put(FOTO_PROFESSOR, foto);
      contentValues.put(HORARIO_CADASTRO_PROFESSOR, horarioCadastro);

      long resultado = banco.insert(TABELA_PROFESSOR, null, contentValues);

      if(resultado != - 1){
           return false;
      }
      else{
           return true;
      }
 }

 	 public boolean inserirAlunoBanco(String nome, String cpf, byte[] foto, String horarioCadastro){
	   SQLiteDatabase banco = this.getWritableDatabase();

	   ContentValues contentValues = new ContentValues();
	   contentValues.put(NOME_ALUNO, nome);
	   contentValues.put(CPF_ALUNO, cpf);
	   contentValues.put(FOTO_ALUNO, foto);
	   contentValues.put(HORARIO_CADASTRO_ALUNO, horarioCadastro);
	   contentValues.put(FK_ID_ALUNO_ENDERECO, ID_ENDERECO);

	   long resultado = banco.insert(TABELA_ALUNO, null, contentValues);

	   if(resultado == - 1){
			return false;
	   }
	   else{
			return true;
	   }
  }

Como preencho o campo FK_ID_PROF_ENDERECO da tabela Professor e FK_ID_ALUNO_ENDERECO da tabela aluno sem erros e garantido que o Endereço cadastrado seja do Aluno/Professor?

Não está assim nos códigos, mas já testei fazendo o seguinte:

  • No método de inserção do Endereco, retornei o ID dele;
  • No ato de inserir um professor, insiro o ID do Endereço no campo da chave estrangeira do professor no (banco.insert(TABELA, null, contentValues); )

Pra mim isso é uma gambiarra kk… por isso que preciso saber como faz essa IMPLEMENTAÇÃO no banco de dados do SQLite

Desde já agradeço pela ajuda!

O problema está no fato de você estar usando um auto_increment. Não tem como saber a priori qual é o ID do endereço antes de fazer o insert, sem fazer algum tipo de select.

A solução que você tentou antes (inserir e retornar o id) é viável. Pode fazer isso dentro de uma transaction.

Outra alternativa é a própria aplicação gerar os IDs. Pode usar um UUID, por exemplo. Assim você sabe o ID a priori, basta inserir os dois registros na mesma transaction com o ID gerado.

O autoincrement só serve pra auto incrementar, enumerar em ordem numérica.
Quanto ao ID do endereço, eu insiro ele junto ao professor/aluno. Nessa hora eu pego o id do endereco e passo na fk do professor/aluno. Pra mim a inconsistência está no ato do cadastro do professor/aluno, será que eles poderiam pegar o mesmo ID caso façam suas matriculas ao msm tempo? Ou não tem chance de correr risco?

Eu fiz e deu certo, mas não sei se é padrão fazer isso, justamente pq pode haver alguma inconsistência, por exemplo, a que falei acima.

Desculpa a ignorância, não sei oq é “UUID”… mas tipo, “Outra alternativa é a própria aplicação gerar os IDs”, isso é feito já no autoincrement.

NO BANCO DE DADOS, a implementação que fiz, onde a inserção do endereço retorna seu ID é essa:

 public String inserirEnderecoBanco(String estado, String cidade, String bairro, String rua, String num, String compl, String pais, String cep){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(PAIS_ENDERECO, pais);
      contentValues.put(ESTADO_ENDERECO, estado);
      contentValues.put(CIDADE_ENDERECO, cidade);
      contentValues.put(BAIRRO_ENDERECO, bairro);
      contentValues.put(RUA_ENDERECO, rua);
      contentValues.put(NUMERO_ENDERECO, num);
      contentValues.put(COMPLEMENTO_ENDERECO, compl);
      contentValues.put(CEP_ENDERECO, cep);

      long resultado = banco.insert(TABELA_ENDERECO, null, contentValues);

      if(resultado == -1){
           return null;
      }
      else{
           Cursor enderecoPesquisado = banco.rawQuery("SELECT * FROM " + TABELA_ENDERECO + " WHERE " + CEP_ENDERECO + " = ?", new String []{cep});
           if(enderecoPesquisado != null){
                enderecoPesquisado.moveToFirst();
                if(enderecoPesquisado.getCount() > 0){
                     String idEnder = enderecoPesquisado.getString(enderecoPesquisado.getColumnIndex(ID_ENDERECO)); // Retorna o ID do endereco cadastrado com esse CEP
                     return idEnder;
                }
                else{
                     return null;
                }
           }
           else{
                return null;
           }
      }
 }

E a inserção do aluno é essa:

 public boolean inserirAlunoBanco(String nome, String cpf, byte[] foto, String horarioCadastro, String idEndereco){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(NOME_ALUNO, nome);
      contentValues.put(CPF_ALUNO, cpf);
      contentValues.put(FOTO_ALUNO, foto);
      contentValues.put(HORARIO_CADASTRO_ALUNO, horarioCadastro);
      contentValues.put(FK_ID_ALUNO_ENDERECO, idEndereco);

      long resultado = banco.insert(TABELA_ALUNO, null, contentValues);

      if(resultado == - 1){
           return false;
      }
      else{
           return true;
      }
 }

Passo o ID do endereço nessa variável idEndereco do inserirAlunoBanco.

NA ACTIVITY EU CHAMA O MÉTODO inserirAlunoBanco E O inserirEnderecoBanco juntos. Com isso tenho todos os parâmetros, tanto do endereço como do aluno, nessa hora, passo o ID do endereço (segundo o CEP cadastrado) no FK do aluno, dessa forma:

 public void inserirAluno(String nome, String cpf, ImageView foto){
      byte[] baFoto = converteImageViewEmByteArray(foto);
      String horarioCadastro = relogio();
      tvRelogio.setText(horarioCadastro);

      // Retorna o ID do endereco cadastrado
      String idEndereco = banco.inserirEnderecoBanco(estado.getText().toString(), cidade.getText().toString(), bairro.getText().toString(), rua.getText().toString(), num.getText().toString(), compl.getText().toString(), pais.getText().toString(), cep.getText().toString());
      boolean resultadoInserir = banco.inserirAlunoBanco(nome, cpf, baFoto, horarioCadastro, idEndereco);

      if(idEndereco != null && resultadoInserir){
           Toast.makeText(this, "Sucesso!", Toast.LENGTH_SHORT).show();
      }
      else{
           Toast.makeText(this, "Falha!", Toast.LENGTH_SHORT).show();
      }
 }

Funcionou? funcionou! Mas não sei se tô fugindo à regra de implementação do ID na FK, pois fiz de cabeça msm, não segui nenhuma regra.

Digo isso pq, por ex., eu ía começar a implementar as FKs sem antes fazer uma modelagem pra saber a cardinalidade, onde aplicar a Foreign key… etc. Se eu não seguisse a regra da modelagem antes, não implementaria meu banco da forma certa. Esse é meu medo, não está implementando da forma certa.

Gostaria que alguém me ajudasse na implementação do ID de uma classe na FK de outra classe, caso haja uma forma padrão já certa já de implementar as FKs. Obg!

É assim que tens de fazer. Ao inserir um registo na BD tens de retornar o ID gerado para poderes utilizador como FK em outras tabelas.

Obg!

Sim, eu sei. É esse o problema. O ID é gerado no banco e você não tem como saber qual o ID sem fazer um select (antes ou depois do primeiro insert).

É pra isso que existem transactions. A operação inteira é feita de forma atômica.

Não, não é. Não é a aplicação que está gerando o ID, é o banco de dados. E é por isso que você precisa fazer esse “vai e volta” pra descobrir qual é o ID e colocar na chave estrangeira do segundo registro. E esse approach funciona, mas se você quiser evitar uma violação de constraint (o endereço foi apagado, por exemplo, entre o primeiro e o segundo insert), deve fazer tudo dentro da mesma transaction.

UUID é um identificador teoricamente único. É uma string. Você pode gerar ela na aplicação e fazer o insert inteiro sem precisar fazer um select pra descobrir o ID do endereço (afinal vc que gera esse ID no código). Ao invés de um inteiro com auto increment, o tipo da chave do endereço seria uma string de tamanho fixo (ou o próprio tipo UUID como alguns bancos suportam).

1 curtida

Eu vejo os IDs! (No ato do cadastro do Aluno e do Endereço que é feito JUNTO).
Veja bem… O método inserirEnderecoBanco no banco de dados retorna o ID do Endereço quando passo o CEP do mesmo. Isso é feito quando estou inserindo um aluno (o Endereço é inserido JUNTO, por isso dá pra pegar o CEP no ato do cadastro do Aluno e passar ele no método inserirEnderecoBanco, com isso eu tenho NO retorno o ID e coloco no FK do aluno cadastrado). Segue código do método inserirEnderecoBanco :

 public String inserirEnderecoBanco(String pais, String estado, String cidade, String bairro, String rua, String num, String compl, String cep){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(PAIS_ENDERECO, pais);
      contentValues.put(ESTADO_ENDERECO, estado);
      contentValues.put(CIDADE_ENDERECO, cidade);
      contentValues.put(BAIRRO_ENDERECO, bairro);
      contentValues.put(RUA_ENDERECO, rua);
      contentValues.put(NUMERO_ENDERECO, num);
      contentValues.put(COMPLEMENTO_ENDERECO, compl);
      contentValues.put(CEP_ENDERECO, cep);

      long resultado = banco.insert(TABELA_ENDERECO, null, contentValues);

      if(resultado == -1){
           return null;
      }
      else{
           Cursor enderecoPesquisado = banco.rawQuery("SELECT * FROM " + TABELA_ENDERECO + " WHERE " + CEP_ENDERECO + " = ?", new String []{cep});
           if(enderecoPesquisado != null){
                enderecoPesquisado.moveToFirst();
                if(enderecoPesquisado.getCount() > 0){
                     String idEnder = enderecoPesquisado.getString(enderecoPesquisado.getColumnIndex(ID_ENDERECO)); // Retorna o ID do endereco cadastrado com esse CEP
                     return idEnder;
                }
                else{
                     return null;
                }
           }
           else{
                return null;
           }
      }
 }

Método inserirAluno abaixo:

 public String inserirAluno(String nome, String cpf, ImageView foto, String pais, String estado, String cidade, String bairro, String rua, String num, String compl, String cep){
      if(cpf.equals("")){
           return "PREENCHA O CPF!";
      }
      if(cpfJaCadastrado(cpf)){
           return "CPF JÁ CADASTRADO!";
      }
      else{
           byte[] baFoto = converteImageViewEmByteArray(foto);
           String horarioCadastro = relogio();
           tvRelogio.setText(horarioCadastro);

           String idEndereco = banco.inserirEnderecoBanco(pais, estado, cidade, bairro, rua, num, compl, cep);// Retorna o ID do endereco cadastrado
           boolean resultadoInserir = banco.inserirAlunoBanco(nome, cpf, baFoto, horarioCadastro, idEndereco);// Insere O idEndereco  no FK do Aluno

           if(idEndereco != null && resultadoInserir){
                return "ID_Endereco: " + idEndereco;
           }
           else{
                return "O Aluno  " + nome + "  Não foi Inserido(a)!";
           }
      }
 }

Ao inserir o aluno com seu Endereço, vejo os IDs no retorno do método inserirAluno.

O problema está agora na Activity listarAluno onde eu resgato os dados do aluno no banco de dados da seguinte forma:

               while(resultado.moveToNext()){

                final String idAluno = resultado.getString(resultado.getColumnIndex("ID_ALUNO"));
                String nome = resultado.getString(resultado.getColumnIndex("NOME_ALUNO"));
                String cpf = resultado.getString(resultado.getColumnIndex("CPF_ALUNO"));

                byte[] baFoto = resultado.getBlob(resultado.getColumnIndex("FOTO_ALUNO"));
                ByteArrayInputStream bais = new ByteArrayInputStream(baFoto);
                Bitmap bmFoto = BitmapFactory.decodeStream(bais);

                String horarioCadastro = resultado.getString(resultado.getColumnIndex("HORARIO_CADASTRO_ALUNO"));
                final String fkEndereco = resultado.getString(resultado.getColumnIndex("FK_ID_ALUNO_ENDERECO"));

Instancio o Aluno e seu Endereço da seguinte forma:

aluno = new Aluno(cpf, nome, bmFoto, horarioCadastro, fkEndereco);
endereco = banco.consultaEnderecoPeloIdBanco(aluno.getFkEnderecoAluno());
arrayAlunos.add(aluno); // Adiciona o aluno no arrayAlunos
adapterCustomizado = new AdapterCustomizadoAluno(this, arrayAlunos);
listaDeAlunos.setAdapter(adapterCustomizado);

No Banco de Dados, o método consultaEnderecoPeloIdBanco está implementado da seguinte forma:

 public Endereco consultaEnderecoPeloIdBanco(String id){
      Endereco endereco = new Endereco();
      SQLiteDatabase banco = this.getWritableDatabase();
      Cursor resultado = banco.rawQuery("SELECT * FROM " + TABELA_ENDERECO + " WHERE " + ID_ENDERECO + " = ?", new String []{id});

      if(resultado != null){
           resultado.moveToFirst();
           if(resultado.getCount() > 0){
                String pais = resultado.getString(resultado.getColumnIndex(PAIS_ENDERECO));
                String estado = resultado.getString(resultado.getColumnIndex(ESTADO_ENDERECO));
                String cidade = resultado.getString(resultado.getColumnIndex(CIDADE_ENDERECO));
                String bairro = resultado.getString(resultado.getColumnIndex(BAIRRO_ENDERECO));
                String rua = resultado.getString(resultado.getColumnIndex(RUA_ENDERECO));
                String num = resultado.getString(resultado.getColumnIndex(NUMERO_ENDERECO));
                String compl = resultado.getString(resultado.getColumnIndex(COMPLEMENTO_ENDERECO));
                String cep = resultado.getString(resultado.getColumnIndex(CEP_ENDERECO));

                endereco.setPais(pais);
                endereco.setEstado(estado);
                endereco.setCidade(cidade);
                endereco.setBairro(bairro);
                endereco.setRua(rua);
                endereco.setNum(num);
                endereco.setComplem(compl);
                endereco.setCep(cep);

                return endereco;
           }
           else{
                return null;
           }
      }
      else{
           return null;
      }
 }

Apesar de ver os IDs dos Endereços e Alunos cadastrados em sequencia NO ATO DO CADASTRO, ao listar os alunos e seus dados, só é exibido os últimos IDs e o último Endereço em todos os alunos.
Exibo o aluno clicado na lista da seguinte forma:

box.setMessage("ID_aluno: " + idAluno + "\n FK_aluno" + fkEndereco + "\n\n\n" + aluno.imprimeAluno() + endereco.imprimeEndereco() + "\nClique na Foto p/ Ampliá-la!");

Aqui sim tá a cagada. Ele só exibe o último ID do endereço e do aluno (Não es´ta obedecendo o moveToNext).

Não sei oq é transactions, talvez seja por isso que estou tendo erros na minha implementação.

Me perdoe, mas eu nao entendi o “vai e volta” que tem que ter pra descobrir o ID. Eu tenho ele no método de consulta, onde já tem o SELECT e o insiro na FK do aluno no ato do cadastro deles.

Usa a função last_insert_rowid() pra retornar o último id da conexão que fez o insert.

SELECT last_insert_rowid()

Obg pela atenção, mas tipo… Não quero “retorna o ROWID da última inserção”, eu quero só pegar o Endereço pelo seu ID, que é o FK do Aluno para exibir no meu ListView.

Estou fazendo o SELECT para isso. Ao inserir o Aluno, insiro o Endereço JUNTOS, por isso dá pra pegar o ID do Endereço e passar para a FK do Aluno.

O código do método INSERIRALUNO:

public void inserirAluno(String nome, String cpf, ImageView foto, String pais, String estado, String cidade, String bairro, String rua, String num, String compl, String cep){
      byte[] baFoto = converteImageViewEmByteArray(foto);
      String horarioCadastro = relogio();
      tvRelogio.setText(horarioCadastro);

      String idEndereco = banco.inserirEnderecoBanco(pais, estado, cidade, bairro, rua, num, compl, cep);// Retorna o ID do endereco cadastrado
      boolean resultadoInserir = banco.inserirAlunoBanco(nome, cpf, baFoto, horarioCadastro, idEndereco);

      if(idEndereco != null && resultadoInserir){
           Toast.makeText(this, "ID_Endereco: " + idEndereco, Toast.LENGTH_SHORT).show();
      }
      else{
           Toast.makeText(this, "ID_Endereco: " + "O Aluno  " + nome + "  Não foi Inserido(a)!", Toast.LENGTH_SHORT).show();
      }          
 }

Dá pra ver o ID do Endereço no Toast quando eu insiro o aluno no sistema, mas quando vou exibir tanto o aluno como o endereço NA LISTA (no ListView), eles não são exibido como deveria. Na lista está implementado assim:

while(resultado.moveToNext()){

final String idAluno = resultado.getString(resultado.getColumnIndex("ID_ALUNO"));
String nome = resultado.getString(resultado.getColumnIndex("NOME_ALUNO"));
String cpf = resultado.getString(resultado.getColumnIndex("CPF_ALUNO"));

byte[] baFoto = resultado.getBlob(resultado.getColumnIndex("FOTO_ALUNO"));
ByteArrayInputStream bais = new ByteArrayInputStream(baFoto);
Bitmap bmFoto = BitmapFactory.decodeStream(bais);

String horarioCadastro = resultado.getString(resultado.getColumnIndex("HORARIO_CADASTRO_ALUNO"));
final String fkEndereco = resultado.getString(resultado.getColumnIndex("FK_ID_ALUNO_ENDERECO"));

aluno = new Aluno(cpf, nome, bmFoto, horarioCadastro, fkEndereco);
endereco = banco.consultaEnderecoPeloIdBanco(aluno.getFkEnderecoAluno());

arrayAlunos.add(aluno); // Adiciona o aluno no arrayAlunos
adapterCustomizado = new AdapterCustomizadoAluno(this, arrayAlunos);
listaDeAlunos.setAdapter(adapterCustomizado);

Eles não estão obedecendo o moveToNext da lista. Ele sempre exibe o último ID cadastrado, tanto do Aluno quanto do Endereço, em vez de mostrar os valores corretos (de cada aluno com seu endereço).

Ta confusa sua questão.
Vamos por partes, pra inserir os dados no banco ta tudo ok entao?

Está!

Todos os método eu já mostrei, mas vamos lá. O método que INSERE UM ENDEREÇO NO BANCO é esse:

// Retorna o ID do Endereço cadastrado
public String inserirEnderecoBanco(String pais, String estado, String cidade, String bairro, String rua, String num, String compl, String cep){
          SQLiteDatabase banco = this.getWritableDatabase();

          ContentValues contentValues = new ContentValues();
          contentValues.put(PAIS_ENDERECO, pais);
          contentValues.put(ESTADO_ENDERECO, estado);
          contentValues.put(CIDADE_ENDERECO, cidade);
          contentValues.put(BAIRRO_ENDERECO, bairro);
          contentValues.put(RUA_ENDERECO, rua);
          contentValues.put(NUMERO_ENDERECO, num);
          contentValues.put(COMPLEMENTO_ENDERECO, compl);
          contentValues.put(CEP_ENDERECO, cep);

          long resultado = banco.insert(TABELA_ENDERECO, null, contentValues);

          if(resultado == -1){
               return null;
          }
          else{
               Cursor enderecoPesquisado = banco.rawQuery("SELECT * FROM " + TABELA_ENDERECO + " WHERE " + CEP_ENDERECO + " = ?", new String []{cep});
               if(enderecoPesquisado != null){
                    enderecoPesquisado.moveToFirst();
                    if(enderecoPesquisado.getCount() > 0){
                         String idEnder = enderecoPesquisado.getString(enderecoPesquisado.getColumnIndex(ID_ENDERECO)); // Retorna o ID do endereco cadastrado com esse CEP
                         return idEnder;
                    }
                    else{
                         return null;
                    }
               }
               else{
                    return null;
               }
          }
     }

O método que INSERE UM ALUNO NO BANCO é esse:

 // Método que insere um Aluno no Sistema Escola
 public boolean inserirAlunoBanco(String nome, String cpf, byte[] foto, String horarioCadastro, String idEndereco){
      SQLiteDatabase banco = this.getWritableDatabase();

      ContentValues contentValues = new ContentValues();
      contentValues.put(NOME_ALUNO, nome);
      contentValues.put(CPF_ALUNO, cpf);
      contentValues.put(FOTO_ALUNO, foto);
      contentValues.put(HORARIO_CADASTRO_ALUNO, horarioCadastro);
      contentValues.put(FK_ID_ALUNO_ENDERECO, idEndereco);

      long resultado = banco.insert(TABELA_ALUNO, null, contentValues);

      if(resultado == - 1){
           return false;
      }
      else{
           return true;
      }
 }

Eu chamo esse métodos na Activity InserirAluno no Método abaixo:

public void inserirAluno(String nome, String cpf, ImageView foto, String pais, String estado, String cidade, String bairro, String rua, String num, String compl, String cep){
	if(cpf.equals("")){
		Toast.makeText(this, "PREENCHA O CPF!", Toast.LENGTH_SHORT).show();
	}
	if(cpfJaCadastrado(cpf)){
		Toast.makeText(this, "CPF JÁ CADASTRADO!", Toast.LENGTH_SHORT).show();
	}
	else{
		byte[] baFoto = converteImageViewEmByteArray(foto);
		String horarioCadastro = relogio();
		tvRelogio.setText(horarioCadastro);

		String idEndereco = banco.inserirEnderecoBanco(pais, estado, cidade, bairro, rua, num, compl, cep);// Retorna o ID do endereco cadastrado
		boolean resultadoInserir = banco.inserirAlunoBanco(nome, cpf, baFoto, horarioCadastro, idEndereco);

		if(idEndereco != null && resultadoInserir){
			Toast.makeText(this, "ID_Endereco: " + idEndereco, Toast.LENGTH_SHORT).show();
		}
		else{
			Toast.makeText(this, "O Aluno  " + nome + "  Não foi Inserido(a)!" + idEndereco, Toast.LENGTH_SHORT).show();
		}
	}
}   

Eu vejo os IDs dos ENDERECOS cadastrados no Toast quando cadastro um Aluno.
1, 2, 3…
Mas quando vou ver todos os dados dos alunos no ListView, só é exibido o ID do último aluno cadastrado junto ao ID do último Endereço tbm cadastrado. Isso se repete com todos os alunos cadastrados. É isso que não tô entendendo, eles não estão obedecendo o moveToNext, segue abaixo a implementação:

while(resultado.moveToNext()){

	final String idAluno = resultado.getString(resultado.getColumnIndex("ID_ALUNO"));
	String nome = resultado.getString(resultado.getColumnIndex("NOME_ALUNO"));
	String cpf = resultado.getString(resultado.getColumnIndex("CPF_ALUNO"));

	byte[] baFoto = resultado.getBlob(resultado.getColumnIndex("FOTO_ALUNO"));
	ByteArrayInputStream bais = new ByteArrayInputStream(baFoto);
	Bitmap bmFoto = BitmapFactory.decodeStream(bais);

	String horarioCadastro = resultado.getString(resultado.getColumnIndex("HORARIO_CADASTRO_ALUNO"));
	final String fkEndereco = resultado.getString(resultado.getColumnIndex("FK_ID_ALUNO_ENDERECO"));

	aluno = new Aluno(cpf, nome, bmFoto, horarioCadastro, fkEndereco);
	endereco = banco.consultaEnderecoPeloIdBanco(aluno.getFkEnderecoAluno());

	arrayAlunos.add(aluno); // Adiciona o aluno no arrayAlunos
	adapterCustomizado = new AdapterCustomizadoAluno(this, arrayAlunos);
	listaDeAlunos.setAdapter(adapterCustomizado);  
	
	[ . . . ]
	
	}

No ListView, no setOnItemClickListener está assim:

AlertDialog.Builder box = new AlertDialog.Builder(ListarAlunos.this);
box.setIcon(R.drawable.icone_ok);
box.setTitle("(ALUNO)");
box.setMessage("ID_aluno: " + idAluno + "\n FK_aluno" + fkEndereco + "\n\n\n" + aluno.imprimeAluno() + endereco.imprimeEndereco() + "\nClique na Foto p/ Ampliá-la!");

Deu pra entender agr ou ainda tá confuso? Fui bem específica agr…

O que deixa confuso é misturar etapas diferentes, inserção e visualização. Certificando diretamente no banco de dados que tudo ficou ok, focamos só na visualização.

Já chequei, mas blz, vou rodar aki e lhe mostrar os prints, só um momento, pfv.

Não precisa de print, só voce confirmar mesmo. Se ta tudo ok fazendo select no banco, teria que fazer o mesmo SQL no seu programa.

Sim, está.

Esses são os prints que provam que o Aluno e o Endereço foram cadastrados.

Veja o Snackbar do Cadastro: Esses são os IDs dos ENDEREÇOS, veja que eles foram incrementados 1, 2, 3…

Fiz o listView do aluno e ele exibe os dados do aluno e do endereço, ambos foram inseridos no banco no ato do cadastro do aluno.

O problema é que só aparece os dados do último endereço cadastrado incluindo seu ID que é a FK do aluno cadastrado, essa repetição são em todos os alunos exibidos na ListView. Segue abaixo:

mostra o metodo q vc le os dados

Tá tudo no post, o último que contem os códigos está bem explicado*.

blz

dps de rawquery, insere essa linha:

startManagingCursor(resultado);

O método não é reconhecido.

Vê só, Eu cadastro um enderreço e passo o id dele no fk do aluno. Daí insiro o aluno.

Quando vou visualizar no listView do endereço, vejo todos os dados do endereço normal, cada um sem repetições.

Quando vou visualizar no listView do aluno, vejo todos os dados do aluno normal, cada um sem repetições.

MAS quando vou visualizar os dados do aluno JUNTO aos dados do endereço, ele não exibe osIDS do aluno, nem o ID do endereço, nem os dados do endereço: PAIS, ESTADO.... ELE SIMPLESMENTE MOSTRA O ÚLTIMO ID E DADOS DO ENDEREÇO QUE FOI CADASTRADO.

O print que mostra isso são esses:

Perceba que NOME, CPF HORARIO DE CAD são os que foram inseridos no aluno, nisso ele não dá erro. Mas os dados do endereço junto com os ids, fks, e getId() lá em cima, TODOS são iguais, pois ele está exibindo só o último cadastrado. Ele não tá obedecendo o moveToNext do ListView onde exibo os dados do aluno com o endereço que foram cadastrados JUNTOS.

da um sout no id pra ver q id ele ta pegando