[DESESPERADO]ArrayList

19 respostas
G
ResultSet rs = stmt.executeQuery("SELECT Disciplina FROM questoes GROUP BY Disciplina");

try {
            Class.forName(driver);
            conn = (Connection) DriverManager.getConnection(url, user, pass);
            Statement stmt = (Statement) conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT Disciplina FROM questoes GROUP BY Disciplina");
            
            int x = 0; 
            while(rs.next()) {
                TOTAL_DE_DISCIPLINAS = rs.getRow();
                ArrayList lista = new ArrayList();

                while (x < TOTAL_DE_DISCIPLINAS) {
                    String NOME_ENCONTRADO = rs.getString(x);

                    lista.add(NOME_ENCONTRADO);
                    x++;
                }
            }

            } catch(Exception e) {

         }
    }

Minha intenção com esse código era adicionar cada campo "disciplina" que o resultset achava em uma ArrayList.
E depois criar um elemento JTree para cada um com o seu nome:

int y = 0;
        while (y < TOTAL_DE_DISCIPLINAS) {
            new javax.swing.tree.DefaultMutableTreeNode(lista.get(y));
            y++;
        }

Mas recebo esse erro:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at Questoes.initComponents(Questoes.java:103)
at Questoes.(Questoes.java:21)
at Questoes$1.run(Questoes.java:12)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Que o que em parece, me diz que eu estou tentando acessar um valor não existente na ArrayList.

19 Respostas

F

Opa,

Você está tentando acessar uma posição inválida no seu ResultSet.

Você está incrementando a variável X e fazendo dela o seu indice para acesso ao result.

int x = 0;   
while(rs.next()) {  
   TOTAL_DE_DISCIPLINAS = rs.getRow();  
   ArrayList lista = new ArrayList();
   while (x &lt; TOTAL_DE_DISCIPLINAS) {  
      String NOME_ENCONTRADO = rs.getString("Disciplina");   
      lista.add(NOME_ENCONTRADO);  
      x++;  
   }  
}

Repare que alterei onde tinha x para "Disciplina" dentro do rs.getString(). Acho que isso vai funcionar, você vai pegar o resultado de seu result pelo nome da coluna.
Como você já faz o incremento no seu result pela rs.next().

Espero que isso resolva seu problema.
Abraço

G

O aplicativo rodou, só não criou as disciplinas na JTree. Qual seria o problema?

Nicolas_Fernandes

Crie um nó principal, e vá adicionando as disciplinas neste:

DefaultMutableTreeNode root = new DefaultMutableTreeNode("Disciplinas");

for (String disciplina : listDisciplinas) { // listDisciplinas representa a lista que você leu

   root.add(new DefaultMutableTreeNode(disciplina));
}

Crie um objeto JTree, e passe o root como referência de itens:

JTree myTree = new JTree(root);

Tente assim.

[]s

juliofsn

O Problema é que você está recriando o ArrayList para cada linha do ResultSet, assim ele perde os elementos que haviam sido adicionados anteriormente.

Além disso não vi a utilidade do segundo while, na verdade ele está pegando o número da linha e adicionando várias vezes o mesmo valor ao ArrayList.

Minha dica é essa: instancie o ArrayList fora do primeiro while e mate o segundo while, você pode saber o número de disciplinas chamando o método count do ArrayList.

F

Agora percebi que você está criando a lista sempre.
Isso vai fazer com que você perca as informações sempre.
Tire a criação da lista de dentro do While.
Acho que deve resolver.

Aproveite também as dicas do Nicolas são muito válidas.

Abraço

Nicolas_Fernandes

Outra coisa: Eu faria meu ArrayList tipado. Acho que facilitaria na hora de pegar valores e não ter que ficar usando conversão e tudo o mais.

Para pegar os dados, faria assim:

Primeiro, criaria uma classe para tratar as Disciplinas, com todos os dados dela que existem no BD.

public class Disciplina {

   private Integer id;
   private String   nome;

   // Getters e Setters...
}

Após isso, no método de leitura, faria um ArrayList tipado da minha classe Disciplina, já que estou trabalhando com ela mesmo.

private List<Disciplina> getDisciplinas() throws Exception {

      Connection conn = (Faria uma classe específica  pra trabalhar com a conexão, pra não ficar reescrevendo código);
      
      String sql = "Select Q.Disciplina From Questoes Q Group By Q.Disciplina";

      PreparedStatement pstm = conn.prepareStatement(sql);

      ResultSet rs = pstm.executeQuery();

      List<Disciplina> disciplinas = null;

      if (rs != null) {

         disciplinas = new ArrayList<Disciplina>();

         while (rs.next()) {

             Disciplina disciplina = new Disciplina();
             // preencho os campos de acordo com o resultado da SQL.
             disciplinas.add(disciplina);
         }
      }

      return disciplinas;
   }

Aí, entraria o código que fiz no post acima:

DefaultMutableTreeNode root = new DefaultMutableTreeNode("Disciplinas");  

try {

    for (Disciplina disciplina : getDisciplinas()) {  
   
        root.add(new DefaultMutableTreeNode(disciplina));  
    }  
} catch (Exception ex) { ex.printStackTrace(); }

JTree myTree = new JTree(root);

Dá uma olhada e vê o que acha!

[]s

G

Desculpe, posso parecer meio iniciante demais, mas o NetBeans Diz que a String disciplina é incompatível com a lista(ArrayList), que é do tipo objeto.

Linha: for (String disciplina : lista) {

Nicolas_Fernandes

Ah, sim, isso porque sua ArrayList não é tipada.

Tenta algo assim:

for (Object disciplina : lista) {
 
   root.add(new DefaultMutableTreeNode(disciplina.toString()));    
}

[]s

G

Funcionou perfeitamente! Fico muito grato à você Nicolas. E Obrigado também Fasagri.
Outra Dúvida rapidinha, No meu banco de dados, tem: Matéria, Questão

Como faço para adicionar a Questão exatamente da mesma matéria? Por exemplo, para não haver questões de português na pasta de matemática.

E eu preciso repetir todo o bloco try/catch para adicionar as questões?

Nicolas_Fernandes

Disponha, cara!

No que precisar, estamos aí!

Não esqueça de alterar o título do tópico com “[RESOLVIDO]”!

[]s

G

Eu estava atualziando, desuclpe postei sem ter terminado, leia o post acima do seu.

Nicolas_Fernandes

Hehe… Vamos lá!

Como está modelado o seu Banco?

Eu, particularmente, modelaria essa parte assim:

1 Tabela chamada Disciplinas
ID, Nome

1 Tabela chamada Questoes
ID, Descricao, Disciplina (FK para Disciplinas.ID)

Daí beleza…

Na hora que você clicar na pasta “Matemática”, saiba qual o ID da discplina. Por quê isso?
Porque você pode fazer uma pesquisa do tipo

“Select Q.ID, Q.Descricao, D.Nome
From Questoes Q
Inner Join Disciplinas D On (Q.Disciplina = D.Id)
Where D.Id = Id da Disciplina que você quer”

Assim, vem só da matéria que você quer!

Era isso?

[]s

G

Bem, acontece que é muito tarde para eu desmontar toda minha tabela e montar denovo.

Eu tenho uma(1) tabela chamada questoes

que está assim:

Disciplina / Questão
Mat 2+2
Port Antes de P e B vem… ?
Cie Formiga é um… ?

e eu preciso que as questões de matemática, fiquem em baixo de matemática!

Nicolas_Fernandes

É, se está assim, suas tabelas não estão normalizadas.

Lembre-se que, para uma tabela estar normalizada, não pode haver redundância de dados em suas tuplas!

Você pode fazer algo assim:

Crie a classe Pojo de Questoes:

public class Questao {

   private Integer id;
   private String   disciplina;
   private String   questao;

   // Getters e Setters...
}

Crie um método de pesquisa assim:

private List<Questao> readByExample(Questao questao) throws Exception {  
   
    Connection conn = (Faria uma classe específica  pra trabalhar com a conexão, pra não ficar reescrevendo código);  
      
    String sql = "Select Q.Id, Q.Disciplina, Q.Descricao From Questoes Q Where True";  
   
    if (questao != null && !questao.getDisciplina().isEmpty()) {

       sql += " And Q.Disciplina = '" + questao.getDisciplina() +"'";
    }

    if (questao != null && !questao.getDescricao().isEmpty()) {

       sql += " And Q.Descricao Like '%" + questao.getDescricao() + "%'";
    }

    PreparedStatement pstm = conn.prepareStatement(sql);  
   
    ResultSet rs = pstm.executeQuery();  
   
    List<Questao> questoes = null;  
   
    if (rs != null) {  
   
       questoes = new ArrayList<Questao>();  
   
       while (rs.next()) {  
   
           Questao q = new Questao();  
           // preencho os campos de acordo com o resultado da SQL.  
           questoes.add(q);  
       }  
    }  
    
    return questoes;  
 }

Porque digo assim? Porque fica um método flexível, pois você não tem que criar um método para cada tipo de pesquisa. É só passar um objeto com os dados que quer pesquisar, e voilá!

Se quer ler tudo da tabela:

readByExample(null);

Se quer ler questoes de Português:

Questao questao = new Questao();

questao.setDisciplina("Port");

readByExample(questao);

Se quer ler questoes que contenham a palavra ‘Soma’:

Questao questao = new Questao();

questao.setDescricao("Soma");

readByExample(questao);

E assim por diante!

Agora, pra ficar do modo que você quer:

  1. Leia as disciplinas do modo que está fazendo já.
  2. Dentro do loop para criar os nodes:
    2.1 Quando adicionar a primeira disciplina (Português, por exemplo), mande buscar no BD quais as questões de Português. Adicione como filhas do nó que está sendo colocado. Isso acontecerá para cada disciplina que for lida!

Tente algo assim, e dê o reply!

[]s

G

O problema é que eu queria fazer tudo automático! Quando eu inserisse uma nova disciplina com sua questão, deveria criar um item na JTree com o nome da disciplina (Já fizemos isto) e detectar as questões da matéria e coloca-las como filhas. Mas outra duvida, como colocar como filhas, se não há nomes nas matérias raiz?

G

Pelo amor de deus! Eu estou completamente desesperado!

Nicolas_Fernandes

Nomes na matéria raiz? Como assim? Realmente não entendi :S

É mais ou menos isso?

for (Object questao : lista) {  
   
    Questao d = (Questao) questao;  // Para não fazer essa conversão, eu sugeri a ArrayList tipada.
    
    DefaultMutableTreeNode node = new DefaultMutableTreeNode(); // Nosso nó principal.

    for (Questao quest : readByExample(d)) { // Faça uma pesquisa para todas as questoes da matéria sugerida, e entre num loop para isso.
        
        node.add(new DefaultMutableTreeNode(quest.getDescricao())); // O método readByExample retorna uma ArrayList tipada, o que facilita para nós, sem conversões. Vou adicionando no nó principal cada questão que foi lida.    
    }
    
    root.add(node); // Adiciono o nó com suas respectivas questões.  
}
M

Por que você não cria seu próprio TreeModel que já encapsule toda a lógica?

G

Observe que com essa linha:

root.add(node);

Você está adicionando ao nó principal! e não ao nó das matérias!

Meu código atual:

for (Object disciplina : listaDisci) {
                root.add(new DefaultMutableTreeNode(disciplina.toString()));

                DefaultMutableTreeNode node = new DefaultMutableTreeNode();
                for (Object topico : listaTopic) {

                    node.add(new DefaultMutableTreeNode(topico.toString()));
                }

               root.add(node);
        }

Sim, eu sei não é o que eu desejo de classificar as questões, mas estou testando como adicionar alguma coisa como filho da disciplina, e NÃO DA RAÍZ.

Criado 11 de fevereiro de 2010
Ultima resposta 12 de fev. de 2010
Respostas 19
Participantes 5