SQL: JOIN vs WHERE

Quanti di voi continuano ad usare lo standard SQL dell’89 senza tenere presente il nuovo standard che prevede, tra le altre cose l’utilizzo della Join? A giudicare dal codice molti… e la risposta più frequente è “non serve….”.

Partiamo da un presupposto, a livello di prestazioni non cambia nulla e neanche di “possibilità“… cioè tutto quello che si poteva fare prima si puo fare adesso… allora perchè imparare un costrutto nuovo se non mi da nulla in più? La risposta è LEGGIBILITA’… quando in Java5 uscì il costrutto foreach tutti, o quasi, i programmatori si affrettarono ad usare questo nuovo metodo che rendeva il codice molto più leggibile… non è vero??? Lo stesso sarebbe dovuto valere per la Join ma questo non è successo forse per la poca conoscenza dello standard… facciamo un esempio concreto:

Abbiamo due tabelle

Impiegato(Id, Nome, Cognome, Gruppo)
Gruppo(Id, Nome)

Prima query tutti i nomi degli impiegati ed il nome del gruppo di appartenenza:

WHERE

select Impiegato.Nome, Gruppo.Nome
from Impiegato, Gruppo
where Gruppo.Id = Impiegato.Gruppo

JOIN

select Impiegato.Nome, Gruppo.Nome
from Impiegato inner join Gruppo on Gruppo.Id = Impiegato.Gruppo

Voi direte: “non è che ci sia tutta questa differenza……” facciamo pero un nuovo assunto, un Impiegato può anche non far parte di nessun gruppo e voi volete la stessa lista di prima…. per far “apparire” anche gli impiegati “solitari” sarete costretti a scrivere:

select Impiegato.Nome, Gruppo.Nome grupName
from Impiegato, Gruppo
where Gruppo.Id = Impiegato.Gruppo
union
select Impiegato.Nome, null grupName
from Impiegato
where Impiegato.Gruppo IS NULL

con la Join un semplice:

select Impiegato.Nome, Gruppo.Nome
from Impiegato left outer join Gruppo on Gruppo.Id = Impiegato.Gruppo

Ora qual’è più leggibile e facile da comprendere??? e questo è un esempio idiota…. aggiungete una decina di tabelle in join e una manciata di clausole where “VERE” e avrete la percezione del perchè usare la JOIN….

enjoy, :-D

Perchè odiare IE

Tutti sanno quanto è odioso il browser (??) di Microsoft… non rispetta gli standard ne per l’html ne per il javascript il che rende la programmazione web multi-browser veramente problematica…. ma c’è di più…

Pochi sanno che il nostro amico IE ha introdotto limitazioni sul numero dei CSS caricabili per ogni pagina… in particolare questo numero è 32… ciò significa che se io ho 33 css l’ultimo è (SEMPLICEMENTE!!!!) ignorato…

Ora Jmaki (il framework per la programmazione web di sun) prevede un CSS per ogni componente, che in media, su grandi applicazioni, saranno piu di 32… soluzione??? usare il framework solo per la parte script e html e ridurre il numero dei CSS il più possibile….perdendo comunque, in parte, il vantaggio dell’ordine offerto da jmaki….

Ancora una volta non ci resta che ringraziare Internet Explorer!!!

Creare Una Cache con Java

Quante volte vi sarà capitato di dover creare una “semplice” Cache? Le Librerie che implementano questo comportamento esistono ma a volte sono troppo complicate da implementare… vediamo allora come implementarla con pochissime righe di codice ed usando solo la libreria standard.

La classe che andremo a creare estende la classe LinkedHashMap<T, K> questo tipo di mappa espone il metodo protected boolean removeEldestEntry che risponde alla domanda tolgo l’ultima entry inserita?

Vediamo come abbiamo implementato la classe per rispondere alla nostra esigenza di creare una cache con politica FIFO

public class Cache<T, K> extends LinkedHashMap<T, K> {

private int maxSize = 1;

public Cache(int maxSize) {
this.maxSize = maxSize;
}

@Override
protected boolean removeEldestEntry(java.util.Map.Entry<T, K> eldest) {
return size() > this.maxSize;
}

}

et voilà il gioco è fatto…. vediamo come funziona:

public static void main(String[] args) {

//Creo una cache che contiene fino a 4 elementi

Map<String, Integer> cache = new Cache<String, Integer>(3);

cache.put(“INBOX-1”, 1);
cache.put(“INBOX-2”, 2);
cache.put(“INBOX-3”, 3);
cache.put(“INBOX-4”, 4);

System.out.println(cache);

}

come output abbiamo

{INBOX-2=2, INBOX-3=3, INBOX-4=4}

La chiave piu vecchia INBOX-1 è stata eliminata…. spada no! ;-)

Ma miglioriamo il tutto, invece che FIFO vogliamo che scelga quella che ha l’ultimo accesso più datato poche modifiche al codice ed il gioco è fatto:

nella classe cache aggiungiamo l’override del metodo get in modo da far andare quella acceduta come ultima in classifica

public class Cache<T, K> extends LinkedHashMap<T, K> {
private int maxSize = 1;
//Questo è il metodo aggiunto rispetto a prima
@Override
public K get(Object key) {
K tmpObj = super.get(key);

super.remove(key);

super.put((T)key, tmpObj);

return super.get(key);
}

public Cache(int maxSize) {
this.maxSize = maxSize;
}

@Override
protected boolean removeEldestEntry(java.util.Map.Entry<T, K> eldest) {
return size() > this.maxSize;
}
}

lanciamo questo test

public static void main(String[] args) {

Map<String, Integer> cache = new Cache<String, Integer>(3);

cache.put(“INBOX-1”, 1);
cache.put(“INBOX-2”, 2);
cache.put(“INBOX-3”, 3);
cache.get(“INBOX-1”);
cache.put(“INBOX-4”, 4);

System.out.println(cache);

}

e avremo come output

{INBOX-3=3, INBOX-1=1, INBOX-4=4}

Come ci aspettavamo è stata tolta la seconda entry…..

spada no?

Potere di JAVA ;-)

Impossibile salvare documenti Internet Explorer da un sito Web SSL o con Basic Auth

Nel corso dello sviluppo di una demo per un cliente siamo incappati in un errore stranissimo, quando si tentava di scaricare il file certificate.p12 appariva una finestra con l’errore “Impossibile aprire il sito Internet. Sito non disponibile o non trovato. Riprovare.” la cosa si verificava solo con l’uso di Internet Explorer (6 o 7)… naturalmente la webapp funzionava correttamente con Firefox, Safari, Opera ed anche col nuovissimo Chrome (maledetta Microsoft!!!!)

abbiamo iniziato una ricerca con google e siamo giunti alla pagina http://support.microsoft.com/kb/316431/it e http://support.microsoft.com/kb/222064 dove si parlava di un problema analogo ma non uguale, qui gli incriminati erano 2 header della response:

Pragma: no-cache
Cache-control: no-cache,max-age=0,must-revalidate

Il problema è che nel codice non erano impostati nè l’uno nè l’altro? abbiamo controllato però il pacchetto in response con tcpdump è gli header effettivamente erano presenti…. non restava che capire chi inseriva questi header… siamo giunti alla pagina http://wiki.jboss.org/wiki/DownloadSSLAndIE6 dove si capisce che è l’application server ad aggiungere tali tag, delle due soluzioni abbiamo adottato la piu semplice cioè quella di aggiungere nel codice

response.setHeader("Cache-Control", "cache, must-revalidate");
response.setHeader("Pragma", "public");

in questo modo l’application server (JBoss e Tomcat hanno lo stesso comportamento) non sovrascrive gli header ed è possibile scaricare il file anche da IE…. ;-)