[Résolu]JTable construite à partir d'une requete sql

maxlegrand
[Résolu]JTable construite à partir d'une requete sql

Bonjour,

j'ai écrit un programme qui devrait me permettre d'afficher dans une JTable le résultat d'une requête sql.
Avant d'écrire mon programme avec une requête sql, je l'ai testé avec des données fixées.
C'est le programme suivant qui fonctionne :

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

import java.util.List;
import java.util.ArrayList;
import java.util.Random;

public class Divers extends AbstractTableModel{
	private static final long serialVersionUID = 1L;
 
	String[] colonnes = {"Nom", "Prenom", "Age"};
	//la liste du contenu du tableau 
	private List<Object[]> allLignes = new ArrayList<Object[]>();
 	
	public Divers(){}
	
	//constructeur avec la liste
	public Divers(List<Object[]> allLignes){
		//test si la liste est vide rajouter une ligne vide
		if (allLignes == null || allLignes.size()<1){
			allLignes.add(new Object[colonnes.length]);
		}
		this.allLignes = allLignes;
	}
 
	/* retourne le nombre d'element de la colonne */
	public int getColumnCount() {
		return colonnes.length;
	}

	/* retourne le nombre de lignes */
	public int getRowCount() {
		return allLignes.size();
	}

	/* retourne le nom de la colonne */
	public String getColumnName(int col) {
		return colonnes[col];	
	}
	
	/* retourne la valeur à la ligne row et colonne col */
	public Object getValueAt(int row, int col) {
		return allLignes.get(row)[col];
	}

	public Class<?> getColumnClass(int c) {
		return getValueAt(0, c).getClass();
	}

	/* definie les cellules éditables ou non */
	public boolean isCellEditable(int row, int col) {
			return false;
	}
	
	/* permet de modifier l'element en placant value a la ligne row 
	colonne col */
	public void setValueAt(Object value, int row, int col) {
		allLignes.get(row)[col] = value;
		fireTableCellUpdated(row, col); // on signal un changement
	}
	
	//Rempli le tableau
	public void remplie(List<Object[]> lignes){
		allLignes = lignes;
		//On signale le changement des données aux listeners :
		fireTableDataChanged();
	}
	
	//Vide la table
	public void vide(){
		allLignes.removeAll(allLignes);
		fireTableRowsDeleted(0,getRowCount());
	}	
		
	public static void main(String [] args){
		Divers maTable = new Divers();		
		JTable jTable = new JTable(maTable);		
		List<Object[]> donnees = new ArrayList<Object[]>();
		Object [][] data = {
				{"Cardin","Pierre",50},
				{"Lopez", "Hector", 47},
				{"Laurent", "Robert", 29},
				{"Cardetti","Martin",30},
				{"Angel", "Marcos", 47}
		};
		JFrame frame = new JFrame("Divers");
		JScrollPane scroll = new JScrollPane(jTable);
		frame.setSize(300,200);
		frame.add(scroll);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Random r = new Random();
		while(true){		
			maTable.vide();
			int n = r.nextInt(5);
			System.out.println(n +" ");
			for(int i=0; i<n; i++){
				Object [] val = new Object[3];
				for(int j=0; j<3; j++)
					val [j]= data[i][j];
				donnees.add(val);
			}
			((Divers)jTable.getModel()).remplie(donnees);	
			for(Object [] o : donnees){
				for(Object obj : o)
					System.out.print(obj + " ");
			System.out.println("");
			}
			try {
				Thread.sleep(2000);
			}catch(InterruptedException ie){}
		}
	}
}

Comme il fonctionnait, je l'ai modifié pour qu'il focntionne avec le résultat d'une requête sql.
Le soucis, c'est que ça ne fonctionne pas. Lorsque de nouvelles données arrivent, elles ne sont pas prises en compte dans la JTable.
Je crois que le probleme provient de tout ce qui est dans le try{}catch mais je n'arrive pas à savoir pourquoi.
Toutes les 2 secondes, je relance la requete et s'il y a de nouvelles lignes, la JTable doit les prendre en compte or elle ne se met pas à jour...
Voici le code avec la connexion à une base de données :

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

import sun.jdbc.odbc.JdbcOdbcDriver;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.List;
import java.util.ArrayList;

public class Divers2 extends AbstractTableModel{
	private static final long serialVersionUID = 1L;
 
	String[] colonnes = {"Nom", "Prenom", "Age"};
	//la liste du contenu du tableau 
	private List<Object[]> allLignes = new ArrayList<Object[]>();
 	
	public Divers2(){}
	
	//constructeur avec la liste
	public Divers2(List<Object[]> allLignes){
		//test si la liste est vide rajouter une ligne vide
		if (allLignes == null || allLignes.size()<1){
			allLignes.add(new Object[colonnes.length]);
		}
		this.allLignes = allLignes;
	}
 
	/* retourne le nombre d'element de la colonne */
	public int getColumnCount() {
		return colonnes.length;
	}

	/* retourne le nombre de lignes */
	public int getRowCount() {
		return allLignes.size();
	}

	/* retourne le nom de la colonne */
	public String getColumnName(int col) {
		return colonnes[col];	
	}
	
	/* retourne la valeur à la ligne row et colonne col */
	public Object getValueAt(int row, int col) {
		return allLignes.get(row)[col];
	}

	public Class<?> getColumnClass(int c) {
		return getValueAt(0, c).getClass();
	}

	/* definie les cellules éditables ou non */
	public boolean isCellEditable(int row, int col) {
			return false;
	}
	
	/* permet de modifier l'element en placant value a la ligne row 
	colonne col */
	public void setValueAt(Object value, int row, int col) {
		allLignes.get(row)[col] = value;
		fireTableCellUpdated(row, col); // on signal un changement
	}
	
	//Rempli le tableau
	public void remplie(List<Object[]> lignes){
		allLignes = lignes;
		//On signale le changement des données aux listeners :
		fireTableDataChanged();
	}
	
	//Vide la table
	public void vide(){
		allLignes.removeAll(allLignes);
		fireTableRowsDeleted(0,getRowCount());
	}	
		
	public static void main(String [] args){
		Divers2 maTable = new Divers2();		
		JTable jTable = new JTable(maTable);
		List<Object[]> donnees = new ArrayList<Object[]>();
	
		//Parametre de connexion a la base de données
		String url="jdbc:odbc:TABLE";
    String login = "root";
    String password = "root";
    Connection connection = null;
		
    JFrame frame = new JFrame("Divers");
		JScrollPane scroll = new JScrollPane(jTable);
		frame.setSize(300,200);
		frame.add(scroll);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		try{
			Driver monDriver = new JdbcOdbcDriver();
			DriverManager.registerDriver(monDriver);	
			connection=DriverManager.getConnection(url,login,password);
			Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
			String sql = "SELECT * FROM TABLE.PERSONNEL";
			while(true){		
				maTable.vide();
				ResultSet rs = stmt.executeQuery(sql);
				ResultSetMetaData rsmd = rs.getMetaData();
				int ncols = rsmd.getColumnCount();
				//Remise du curseur à sa position initiale
				rs.beforeFirst();
				boolean suivant = rs.next();
				while(suivant){
					Object val [] = new Object[ncols];
					for(int j=1; j<=ncols; j++)
						val[j-1] = rs.getString(j);
					donnees.add(val);
					suivant = rs.next();
				}		
				((Divers2)jTable.getModel()).remplie(donnees);	
				//Remise du curseur à sa position initiale
				rs.beforeFirst();
				try {
					Thread.sleep(2000);
				}catch(InterruptedException ie){}	
			}
		}catch(Exception e){}
	}
}
fredericmazue

Quote:
la JTable doit les prendre en compte or elle ne se met pas à jour...

C'est parce qu'une JTable ne se met pas à jour lorsqu'on change le contenu du modèle de données. C'est comme ça :(
Il faut changer l'instance du modèle lui même ou coder....
maxlegrand

fredericmazue wrote:
Quote:
la JTable doit les prendre en compte or elle ne se met pas à jour...

C'est parce qu'une JTable ne se met pas à jour lorsqu'on change le contenu du modèle de données. C'est comme ça :(
Il faut changer l'instance du modèle lui même ou coder....

Je comprends pas :oops:
Dans le 1er code, il est normal que cela fonctionne et pas dans le second ?
Parce que dans le 1er code que j'ai posté, on voit la JTable passé de 0 à 2 lignes puis 1 puis 2 etc ...
La JTable se modifie.
fredericmazue

Très franchement je ne sais plus :oops:
Il y a longtemps que je n'ai pas mis mon groin là-dedans.
Mais ta question telle que tu l'as posée m'a rappelé un problème de rafraîchissement de JTable que j'avais déjà vu.
Mais peut être que je confonds avec autre chose. :oops:
J'ai jeté un coup d'oeil rapide à ton code et pour moi il devrait marcher, puisque fireTableDataChanged est appelé. C'est peut être bien l'absence de cet appel que j'avais en tête, je ne sais plus. S'il n'y a pas cet appel explicite, la table n'est pas rafraichie, ça c'est sûr. Mais comme l'appel est dans ton code, ça devrait marcher.

Es tu sûr que les données qui arrivent sont bien différentes à chaque fois ?

maxlegrand

fredericmazue wrote:
Très franchement je ne sais plus :oops:
Il y a longtemps que je n'ai pas mis mon groin là-dedans.
Mais ta question telle que tu l'as posée m'a rappelé un problème de rafraîchissement de JTable que j'avais déjà vu.
Mais peut être que je confonds avec autre chose. :oops:
J'ai jeté un coup d'oeil rapide à ton code et pour moi il devrait marcher, puisque fireTableDataChanged est appelé. C'est peut être bien l'absence de cet appel que j'avais en tête, je ne sais plus. S'il n'y a pas cet appel explicite, la table n'est pas rafraichie, ça c'est sûr. Mais comme l'appel est dans ton code, ça devrait marcher.

Es tu sûr que les données qui arrivent sont bien différentes à chaque fois ?


Toutes les 2 secondes la requete est lancée mais s'il n'y a eu aucun changement dans la base de données, la JTable reste en l'état.
La JTable se remplit mais ne prend pas en compte les changements lorqu'ils ont lieu.
Pour savoir si la table devrait avoir de nouvelles lignes, je lance mon programme écrit en java et la requete sur le serveur sql.
Au lancement du programme et de la requete pas de soucis, les résultats sont les mêmes.
Mais pour les suivantes quand la requete sur le serveur sql fournit de nouvelles lignes, la JTable elle ne s'est pas modifiée.
Je ferme ma fenetre puis je relance le programme et les nouvelles lignes apparaissent.
Le probleme doit donc se situer au niveau de l'écriture de la requete sql mais j'ai effectué quelques tests sans succés.
Niroken

Je n'ai pas regarder en détail ton code mais qq chose me chiffonne

Tu as fais un bloc
try
{[code]} -> bien
catch{Exception e}
{}

Le soucis c'est que si tu catch une exception tu ne l'affiches pas
et donc il est normal qu'il ne se passe rien si une exception est
levée.

je mettrais
catch{Exception e}
{
e.printStackTrace();
}

et observer si tu as des messages d'erreur sur ta console de sortie

Si non c'st effectivement un problème de rafraichissement de JTable

Bonne chance à toi

maxlegrand

Probleme résolu :lol:
Il suffisait juste de mettre tout ce qui concernait la connexion à la BDD et la requete sql entre le bloc try{}catch.

fredericmazue

Quote:
Il suffisait juste de mettre tout ce qui concernait la connexion à la BDD et la requete sql entre le bloc try{}catch.

Ca n'y était pas déjà ? :shock:
Hum je vois, il y avait un timeout sur la connexion ou quelque chose comme ça. Du côté du SDGBR je veux dire.
En tout cas ça montre la pertinence de la remarque de Niroken: ne jamais museler une exception. Dans ce cas tu aurais vu tout de suite ce dont il s'agissait.
maxlegrand

fredericmazue wrote:
Quote:
Il suffisait juste de mettre tout ce qui concernait la connexion à la BDD et la requete sql entre le bloc try{}catch.

Ca n'y était pas déjà ? :shock:
Hum je vois, il y avait un timeout sur la connexion ou quelque chose comme ça. Du côté du SDGBR je veux dire.
En tout cas ça montre la pertinence de la remarque de Niroken: ne jamais museler une exception. Dans ce cas tu aurais vu tout de suite ce dont il s'agissait.

Oui c'est vrai :lol:
C'était plutot dans la boucle while(true). En tous les cas, c'est réglé.