venerdì 29 luglio 2011

Ordinare liste usando java.lang.Comparable e java.util.Comparator


Per ordinare liste di oggetti in Java sono a disposizione  due interfacce:

  • java.lang.Comparable
  • java.util.Comparator

L’interfaccia java.lang.comparable di solito si utilizza per definire l’ordinamento “naturale” di un oggetto e consta di un metodo con firma

 int compareTo(T o)

che paragona l’oggetto corrente (this) con l’oggetto fornito in input al metodo (o).
Il risultato sarà:
  • un intero positivo se this>o
  • 0 se sono uguali
  • un intero negativo se this<0

Vediamo un esempio



public class Persona implements Comparable<Persona> {
       public Persona(){
            
       }
       public Persona(String nome,String cognome,int eta){
             this.nome=nome;
             this.cognome=cognome;
             this.eta=eta;
       }
       private String nome;
       private String cognome;
       private int eta;
       public String getNome() {
             return nome;
       }
       public void setNome(String nome) {
             this.nome = nome;
       }
       public String getCognome() {
             return cognome;
       }
       public void setCognome(String cognome) {
             this.cognome = cognome;
       }
       public int getEta() {
             return eta;
       }
       public void setEta(int eta) {
             this.eta = eta;
       }
       @Override
       public int compareTo(Persona o) {
            
             return this.cognome.compareTo(o.cognome);
       }
       public String toString(){
             StringBuffer sb=new StringBuffer();
            
             sb.append(this.cognome);
             sb.append("  ");
             sb.append(this.nome);
             sb.append("  ");
             sb.append(this.eta);
            
             return sb.toString();
       }

}










































L’ordinamento definito è sul cognome; si noti che utilizziamo il metodo compareTo dell’oggetto String che di default ordina in modo alfabetico crescente (A-Z).

L’interfaccia java.util.Comparator si utilizza invece quando si vogliono definire ordinamenti alternativi dell’oggetto.
Si crea dunque una classe a parte che implementa l’interfaccia con il seguente metodo:

public int compare(T a,T b);

Il risultato sarà:
  • un intero positivo se a>b
  • 0 se sono uguali
  • un intero negativo se a<b

Vediamo un comparator che ordini le persone per età:

import java.util.Comparator;

public class PersonaEtaComparator implements Comparator<Persona> {

      @Override
      public int compare(Persona p1, Persona p2) {
            int retVal=0;
            if(p1.getEta()>p2.getEta())
            {
                  retVal=1;
            }
            else if(p1.getEta()<p2.getEta())
            {
                  retVal=-1;
            }
            return retVal;
      }

}


A questo punto vediamo il risultato eseguendo il seguente main; procederemo prima alla stampa dei record così come sono inseriti, poi ordinandoli per ordinamento naturale ed infine per età.




public class TestOrdinamento {

      /**
       * @param args
       */
      public static void main(String[] args) {
            LinkedList<Persona> lista=new LinkedList<Persona>();
            popolaPersona(lista);
            System.out.println("Non ordinata>>"+lista);
            Collections.sort(lista);
            System.out.println("Ordinamento Naturale>>"+lista);
            Collections.sort(lista,new PersonaEtaComparator());
            System.out.println("Ordinamento per età>>"+lista);

      }
      private static void popolaPersona(LinkedList<Persona> lista)
      {
            lista.add(new Persona("mario","rossi",25));
            lista.add(new Persona("luigi", "bianchi", 55));
            lista.add(new Persona("mario","verdi",14));
            lista.add(new Persona("luigi", "gialli", 45));
            lista.add(new Persona("mario","maffei",32));
            lista.add(new Persona("luigi", "servillo", 56));
      }

}



L’output prodotto dalle 3 liste sarà:


Non ordinata>>[rossi  mario  25, bianchi  luigi  55, verdi  mario  14, gialli  luigi  45, maffei  mario  32, servillo  luigi  56]

Ordinamento Naturale>>[bianchi  luigi  55, gialli  luigi  45, maffei  mario  32, rossi  mario  25, servillo  luigi  56, verdi  mario  14]

Ordinamento per età>>[verdi  mario  14, rossi  mario  25, maffei  mario  32, gialli  luigi  45, bianchi  luigi  55, servillo  luigi  56]














mercoledì 27 luglio 2011

MySql modificare un trigger

In questo post vediamo una caratteristica (piuttosto scomoda) di Mysql, ossia il fatto che un trigger , una volta creato, non è  più modificabile.
Praticamente non esiste una istruzione del tipo “alter trigger”e bisogna necessariamente cancellarlo (drop trigger [nome_trigger]) e ricrearlo.
Vediamo un esempio completo

NOTA: In Mysql , quando si lancia uno script per creare una tabella oppure una stored procedure oppure un trigger, il carattere “;” è utilizzato come delimitatore standard.
Praticamente se si lancia uno script al primo ;  Mysql ritiene chiuso lo stesso script; per questo motivo usando le Stored Procedure oppure i trigger da riga di comando è necessario cambiare i delimitatori.

Data una semplice tabella anagrafica con questa struttura:


CREATE TABLE  `actionbazaar`.`anagrafica` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nome` varchar(45) NOT NULL,
  `cognome` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 


Vogliamo realizzare un trigger che, per ogni delete sulla tabella anagrafica vada a scrivere il record di cancellazione su una  tabella così definita.




CREATE TABLE  `actionbazaar`.`anagrafica_clone` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nome` varchar(45) NOT NULL,
  `cognome` varchar(45) NOT NULL,
  `cancellazione` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 












Il nostro trigger sarà definito in questo modo:


delimiter $$
create trigger tr_anagrafica_canc
after delete on anagrafica
for each row
begin
insert into actionbazaar.anagrafica_clone(nome,cognome)
values(old.nome,old.cognome);
end $$
delimiter ;

 







Per “ritrovare” la sintassi di creazione del trigger lanciare il comando show triggers,
nel nostro caso avremo


mysql> show triggers \G
*************************** 1. row ***************************
             Trigger: tr_anagrafica_canc
               Event: DELETE
               Table: anagrafica
           Statement: begin
insert into actionbazaar.anagrafica_clone(nome,cognome)
values(old.nome,old.cognome);
end
              Timing: AFTER
             Created: NULL
            sql_mode: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
             Definer: root@localhost
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: latin1_swedish_ci
1 row in set (0.02 sec)
 




Dobbiamo quindi salvarci queste informazioni, effettuare la drop trigger tr_anagrafica_canc e successivamente ricrearlo con le opportune modifiche.

martedì 26 luglio 2011

Generare password random in javascript


La funzione accetta in input una lunghezza e quindi genera valori casuali scegliendoli tra una lista di caratteri prestabiliti.
Esempio:


function randomPassword(length)
{
  chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/=!";
  pass = "";
  for(x=0;x<length;x++)
  {
    i = Math.floor(Math.random() * 65);
    pass += chars.charAt(i);
  }
  return pass;
}



Per testare l’input utente(vogliamo che sia un intero senza virgola) utilizziamo la function isNumeric così definita (cicliamo tra i caratteri per riscontrare che ogni carattere sia valido):


function IsNumeric(sText)

{
   var ValidChars = "0123456789";
   var IsNumber=true;
   var Char;


   for (i = 0; i < sText.length && IsNumber == true; i++)
      {
      Char = sText.charAt(i);
      if (ValidChars.indexOf(Char) == -1)
         {
         IsNumber = false;
         }
      }
   return IsNumber;
  
   }






La funzione richiamata dal form al click del bottone sarà quindi:

function scriviPassword(){
var length=document.getElementById("txtLength").value;

if(IsNumeric(length))
{
 if(parseInt(length)>6){
 var pass=randomPassword(length);

 document.getElementById("divPassword").innerHTML=pass;
 }
 else
 {
    alert('Attenzione una password deve essere lunga almeno 6 caratteri!!');
   }
}
else
{
alert('Errore, la lunghezza specificata non è un numero!!!');


}

}


 Di seguito l'esempio completo HTML:
Inserire lunghezza password:

lunedì 25 luglio 2011

Leggere e scrivere campi Blob usando Java e JDBC


Nell’esempio vediamo come scrivere un programma java che si occupa di scrivere dati in formato blob su una tabella e poi successivamente leggere il file scritto e salvarlo sul proprio file system.
Come Db Server ho utilizzato MySql 5.5.
La tabella target ha la seguente struttura:

CREATE TABLE  `actionbazaar`.`testblob` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `nomeFile` varchar(45) NOT NULL,
  `contenuto` longblob NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;


Il campo “nomeFile” indica il nome con cui è identificato il nostro file, mentre il campo contenuto è di tipo LONGBLOB.
Mysql ha 4 tipi di dato per gestire i campi blob:

  • TinyBlob (256 bytes)
  • Blob (64 kb)
  • MediumBlob (16MB)
  • LongBlob (4GB)

Il progetto Java si connette al db utilizzando JDBC  e il driver di connessione mysql-connector 5.1.10 (è un jar da aggiungere al classpath del progetto).

Scrivere Blob su Db

Per scrivere il file su Db utilizziamo la proprietà del PreparedStatement setBinaryStream, che si occupa di inviare direttamente un inputStream come parametro.

Il codice completo del metodo di inserimento è il seguente:


/**
        * Codice per l'inserimento BLOB su Tabella
        * @param conn - la connessione
        * @param nomeFile- la Stringa con cui identifichiamo il file sul db (campo nomeFile)
        * @param file - il file del nostro filesystem che vogliamo portare su Db
        * @throws Exception
        */
       private void inserisciBlob(Connection conn,String nomeFile,File file) throws Exception{
             BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
             String sql="insert into actionbazaar.testblob(nomeFile,contenuto) values (?,?)";
             PreparedStatement pst=conn.prepareStatement(sql);
             pst.setString(1, nomeFile);
             pst.setBinaryStream(2, bis);
             pst.executeUpdate();
             pst.close();
       }


Leggere Blob da Db

Per leggere il file da db utilizziamo invece la proprietà getBinaryStream che ci torna un InputStream che poi leggiamo e scriviamo sul nostro File.



       /**
        * Metodo che recupera il file da db e lo salva su filesystem
        * @param conn - la connessione
        * @param discrimen - il campo nomeFile su tabella che identifica il nostro blob
        * @param file - il file di output che scriveremo sul nostro File System
        * @throws Exception
        */
       private void leggiBlob(Connection conn,String discrimen,File file) throws Exception{
             String sql="select contenuto from actionbazaar.testblob where nomeFile=?";
             PreparedStatement pst=conn.prepareStatement(sql);
             BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));
            
             pst.setString(1, discrimen);
             ResultSet rs=pst.executeQuery();
             while(rs.next()){
                    InputStream is= rs.getBinaryStream("contenuto");
                    byte[] buffer = new byte[256];
                    while (is.read(buffer) > 0) {
                     bos.write(buffer);
                    }
             }
             bos.close();
       }




Il metodo main del nostro programma sarà quindi il seguente:



public static void main(String[] args) {
             Connection conn=null;
             ReadWriteBlobFields rbf=new ReadWriteBlobFields();
             try
             {
                    Class.forName(DRIVER);
                    conn=DriverManager.getConnection(URL,USERNAME,PASSWORD);
                    System.out.println("Connessione effettuata....");
                    rbf.inserisciBlob(conn, "linux", new File("c:/temp/com_linux.pdf"));
                    File fOut=new File("out/linux.pdf");
                    rbf.leggiBlob(conn, "linux", fOut);
                    conn.close();
                    System.out.println("Procedura terminata correttamente");
             }
             catch(Exception ex){
                    ex.printStackTrace();
                    try {
                           conn.close();
                    } catch (SQLException e) {
                           // TODO Auto-generated catch block
                           e.printStackTrace();
                    }
             }

       }