In questo articolo, analizziamo gli strumenti messi a disposizione dalla libreria JFree-Chart che ci permettono di generare i grafici, acquisendo i dati direttamente dal database. JFreeChart, infatti, prevede una serie di classi wrapper che permettono di organizzare i dati in un formato specifico, compatibile con il motore di rendering della libreria.
Per generare un grafico con la libreria JfreeChart, occorre creare un dataset specifico per la tipologia di grafico che intendiamo creare. Grazie alle classi wrapper poi, non dobbiamo far altro che fornire la connessione al database e la query, che restituisce i dati che ci interessano. Naturalmente la query, deve fornire dei dati compatibili con la classe wrapper che si intende utilizzare.
Le classi wrapper disponibili, sono le seguenti:
- JDBCPieDataset che permette di generare dataset specifici per la rappresentazione di grafici a torta. La query sql utilizzata per automatizzare la generazione del dataset, deve restituire soltanto due colonne: la prima, contenente dati di tipo VARCHAR indicanti le categorie, la seconda, contenente i valori numerici da rappresentare.
- JDBCCategoryDataset che permette di generare dataset specifici per la rappresentazione di grafici a barre, con i dati raggruppati in categorie. In questo caso, la query, deve restituire almeno due colonne: la prima, contenente dati di tipo VARCHAR indicanti le categorie, le rimanenti, devono contenere i valori numerici da rappresentare.
- JDBCXYDataset che permette di generare dataset specifici per la rappresentazione di curve in un classico sistema di assi cartesiani. Anche in questo caso, la query, deve restituire almeno due colonne: la prima, deve contenere i valori numerici da distribuire sull'asse x, le rimanenti, devono contenere i valori numerici da associare ad ogni serie (valori y).
Per capire il funzionamento di queste classi wrapper, esaminiamo qualche esempio pratico.
Ipotizziamo di avere un database MySQL, in cui c'è una tabella ISCRIZIONI
, nella quale sono presenti il numero di iscritti per ciascun corso di laurea per ciascun anno accademico.
ANNO | CORSO_DI_LAUREA | ISCRITTI |
---|---|---|
2005 | INFORMATICA | 54 |
2006 | INFORMATICA | 200 |
2007 | INFORMATICA | 200 |
2008 | INFORMATICA | 295 |
2009 | INFORMATICA | 302 |
2005 | ARCHITETTURA | 65 |
2006 | ARCHITETTURA | 134 |
2007 | ARCHITETTURA | 187 |
2008 | ARCHITETTURA | 165 |
2009 | ARCHITETTURA | 202 |
2005 | ECONOMIA | 133 |
2006 | ECONOMIA | 215 |
2007 | ECONOMIA | 199 |
2008 | ECONOMIA | 205 |
2009 | ECONOMIA | 215 |
Lo script per creare la tabella è il seguente:
CREATE TABLE 'iscritti' ( 'anno' INT( 4 ) NOT NULL , 'corso_di_laurea' VARCHAR( 50 ) NOT NULL , 'iscritti' INT( 4 ) NOT NULL , PRIMARY KEY ( 'anno' , 'corso_di_laurea' ) );
Grafici a torta
Come primo esempio, creiamo un grafico a torta, in cui ciascuna porzione rappresenta il numero di iscritti nell'anno accademico 2009 di un singolo corso di laurea. La query, deve restituire due campi: il corso di laurea e il numero di iscritti. La query è la seguente:
select corso_di_laurea, iscritti from iscritti where anno = 2009
Per ottenere il dataset, è necessario creare un'istanza della classe JDBCPieDataset
. Il costruttore di questa classe riceve un oggetto ti tipo java.sql.Connection
, che rappresenta la connessione al nostro database.
Fatto ciò, richiamiamo il metodo executeQuery()
che riceve in ingresso la query sql da eseguire. Per semplicità ignoriamo la gestione delle eccezioni.
String sql = "select corso_di_laurea, iscritti from iscritti where anno = 2009"; String url ="jdbc:mysql://" + host + "/" + dbname; Class.forName(driver); Connection con = DriverManager.getConnection(url, username, password); JDBCPieDataset dataset = new JDBCPieDataset(con); dataset.executeQuery(sql); con.close();
Ottenuto il dataset, non ci resta che passarlo al motore di rendering per la creazione del grafico vero e proprio. In questo caso creiamo un PieChart
.
JFreeChart chart = ChartFactory.createPieChart(
"ISCRIZIONI",
dataset,
true, true, true);
ChartUtilities.saveChartAsPNG(new java.io.File("torta.png"), chart, 1000, 1000);
Istogrammi
Vediamo come generare un istogramma. Nell'esempio raggruppiamo i dati per anno accademico. Per ciascun anno visualizziamo il numero di iscritti di ciascun corso di laurea. La query, deve restituire 4 campi: l'anno accademico, il numero di iscritti del corso di Informatica per il corrispondente anno accademico, il numero di iscritti del corso di Architettura, e così via per gli altri corsi.
La query da utilizzare in questo esempio è la seguente:
String sql = "SELECT distinct(anno) as anno, (select iscritti from iscritti where corso_di_laurea = 'INFORMATICA' and anno = i.anno) as informatica, (select iscritti from iscritti where corso_di_laurea = 'ARCHITETTURA' and anno = i.anno) as architettura, (select iscritti from iscritti where corso_di_laurea = 'ECONOMIA' and anno = i.anno) as economia FROM iscritti i
La generazione del dataset, è praticamente identica a quella precedente. L'unica differenza è che occorre instanziare una classe JDBCCategoryDataset
.
String sql = "SELECT distinct(anno) as anno, " + " (select iscritti from iscritti where corso_di_laurea = 'INFORMATICA' and anno = i.anno) as informatica," + " (select iscritti from iscritti where corso_di_laurea = 'ARCHITETTURA' and anno = i.anno) as architettura" + " FROM iscritti i"; String url ="jdbc:mysql://" + host + "/" + dbname; Class.forName(driver); Connection con = DriverManager.getConnection(url, username, password); JDBCCategoryDataset dataset = new JDBCCategoryDataset(con); dataset.executeQuery(sql); con.close();
Il rendering del grafico è leggermente differente poiché, in questo caso, occorre utilizzare il BarChart3D
.
JFreeChart chart = ChartFactory.createBarChart3D(
"Istogramma", "Anno", "Numero di iscritti",
dataset,
PlotOrientation.VERTICAL,
true, true, true);
ChartUtilities.saveChartAsPNG(new java.io.File("istogramma.png"), chart, 500, 500);
Grafico lineare
Nell'ultimo esempio, vediamo come generare un classico grafico lineare. Vediamo l'andamento del numero di iscritti per ciascun corso. Utilizziamo la stessa query dell'esempio precedente.
String sql = "SELECT distinct(anno) as anno, " + " (select iscritti from iscritti where corso_di_laurea = 'INFORMATICA' and anno = i.anno) as informatica," + " (select iscritti from iscritti where corso_di_laurea = 'ARCHITETTURA' and anno = i.anno) as architettura" + " FROM iscritti i"; String url ="jdbc:mysql://" + host + "/" + dbname; Class.forName(driver); Connection con = DriverManager.getConnection(url, username, password); JDBCXYDataset dataset = new JDBCXYDataset(con); dataset.executeQuery(sql); con.close();
In questo caso, per il rendering del grafico, occorre utilizzare l'XYLineChart
.
JFreeChart chart = ChartFactory.createXYLineChart( "Istogramma", "Anno", "Numero di iscritti", dataset, PlotOrientation.VERTICAL, true, true, true); ChartUtilities.saveChartAsPNG(new java.io.File("C:\Documents and Settings\Luca\Desktop\function.png"), chart, 400, 500);
È possibile, naturalmente, fornire alle classi che generano il dataset, anche query più complesse, purchè la struttura dati restituita sia rispettata.