giovedì 24 aprile 2014

Query per trovare tabelle e righe totali in un db


Con questa query possiamo trovare tutte le tabelle con il numero di righe ordinate per tabella con più dati

select so.name as NomeTabella,max(si.rows) as righe from sysobjects as so
inner join sysindexes as si
on si.id=so.id and so.xtype='U'
group by so.name
order by 2 desc;

mercoledì 23 aprile 2014

Utility bcp Sql Server

L'utility bcp.exe, presente nelle installazioni di Sql Server di default, ci può servire per scaricarci i dati di una tabella assieme alla struttura.
Vediamo ad esempio come utilizzarla per creare un file di struttura della tabella e dopo per esportare i dati:

Con il comando

bcp domini.dbo.comuni format nul -f c:\comuni.frm -S 127.0.0.1 -U username-P password-n

Creiamo il file struttura specificando grazie al comando -n i dati nativi (quindi se ci sono campi di tipo data etc.)

Il risultato di questo comando è il seguente file:


10.0
3
1       SQLNCHAR            2       510     ""   1     codice avviamento bancario                               Latin1_General_CI_AS
2       SQLNCHAR            2       510     ""   2     denominazione                                            Latin1_General_CI_AS
3       SQLNCHAR            2       510     ""   3     sigla automobilistica                                    Latin1_General_CI_AS


Per esportare i dati possiamo fare così:

bcp domini.dbo.comuni out c:\comuni.dat -S 127.0.0.1 -U username -P password-c -v

L'opzione -c evita che ci sia il prompt per ogni campo e lo scrive di default come character usando sempre di default come separatore il tab tra un campo e l'altro.
Il risultato sarà di questo tipo (qui uno stralcio):


010009 TORINO TO
012005 AOSTA AO
014001 GENOVA GE
016006 MILANO MI
018002 TRENTO TN
020008 VENEZIA VE
022004 TRIESTE TS
024000 BOLOGNA BO
026005 ANCONA AN
028001 FIRENZE FI
030007 PERUGIA PG
032003 ROMA RM
034009 NAPOLI NA
036004 L'AQUILA AQ
038000 CAMPOBASSO CB
040006 BARI BA
042002 POTENZA PZ
044008 CATANZARO CZ
046003 PALERMO PA
......
......


Per ricaricare i dati su un'altra tabella o un altro db occorre invece eseguire il comando

bcp domini2.dbo.BKCR_DOMANDA  in comuni.dat -f comuni.fmt  -e scarico.log -S 127.0.0.1 -U gianos -P gianos -c

L'opzione -e scrive se necessario dei log di errore.

Si noti che per quanto riguarda lo scarico dei dati (creazione del file .dat) è possibile anche scaricare i dati in base ad una query con il seguente comando:

bcp "select TOP 100 * from domini.dbo.comuni" queryout output.txt -S 127.0.0.1 -U gianos -P gianos -c

mercoledì 9 aprile 2014

Log4j utilizzo di MDC (Mapped Diagnostic Context)

Utilizzando la classe org.apache.log4j.MDC è possibile inserire dei parametri in una mappa e poi riutilizzarli nei nostri appender, sfruttando il conversion pattern dell'appender.

Vediamo un esempio.

Per prima cosa dobbiamo definire un Filtro Http che inserisca nella mappa i valori, supponiamo di voler inserire l'indirizzo IP del chiamante.

Filtro


import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.MDC;
public class MyMdcFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
     Utente utente = null;
        try {
         
         String ip = request.getRemoteAddr();
         
         MDC.put("ipHost",ip);
          
            chain.doFilter(request, response);
 
        } finally {
           
      MDC.remove("ipHost");
        }
 
    }

 public void destroy() {
 }

 public void init(FilterConfig arg0) throws ServletException {
 }
 
}


Impostazioni log4j.properties

si noti in particolare la riga in grassetto, che consente di recuperare il valore presente nell'MDC


##############################################################
################### DEFINIZIONE DEI LOGGER ###################
##############################################################



log4j.rootLogger=DEBUG
#Gestione log4j riguardante esclusivamente la comunicazione del Datagroup del log garante.
log4j.logger.MyLogger.logIp=INFO, LogIp


log4j.appender.LogIp=org.apache.log4j.DailyRollingFileAppender
## Inserire il percorso assoluto del file        "
log4j.appender.LogIp.File=
log4j.appender.LogIp.layout=org.apache.log4j.PatternLayout
log4j.appender.LogIp.layout.ConversionPattern=%d{dd-MM-yyyy HH\:mm\:ss} %X{ipHost}  %m%n
log4j.appender.LogIp.DatePattern='.'yyyy-MM-dd'.log'

Caricamento lato web del log4j.properties

Il log4j.properties si può caricare in una Servlet con parametro load on startup pari a 0, ossia una servlet il cui metodo init è richiamato allo start up della Web App


File log4jAppl = new File( PATH_FILE );
// da gestire nel caso in cui il file non sia indicato, si potrebbe loggare internamente 
PropertyConfigurator.configure(log4jProp); 

Utilizzo del logger

Come al solito si utilizzerà il logger richiamandolo così nei punti di interesse:


private static Logger myLog= Logger.getLogger("MyLogger.logIp");


Risultato nel file di log

08-04-2014 19:02:00 10.249.232.187  dati loggati.....;

sabato 5 aprile 2014

Callable vs Runnable

In Java dalla versione 1.0 è presente l'interfaccia java.lang.Runnable, che come sappiamo deve essere implementata da quelle classi che si vuole eseguire come Thread separati.
Nell'interfaccia è dichiarato un solo metodo

void run()

Dalla versione 1.5 invece è stata creata una nuova interfaccia java.util.concurrent.Callable che per certi versi può essere vista come una estensione dell'interfaccia Runnable. Lo scopo dei progettisti è sempre quello di mantenere la retrocompatibilità, e questo è il motivo per cui non hanno modificato l'interfaccia Runnable ma ne hanno creata una nuova.

L'unico metodo definito dall'interfaccia Callable è:

V call() throws Exception

Il vantaggio di utilizzare Callable è che consente di ottenere indietro il risultato dell'esecuzione del task nel thread separato, cosa che tramite Runnable non è possibile.
In generale le differenze tra le 2 interfacce sono le seguenti:

  1. Un oggetto che implementa Callable non può essere utilizzato direttamente per costruire un Thread, mentre un oggetto che implementa Runnable può farlo;
  2. Un oggetto che implementa  Callable torna un risultato mentre un oggetto che implementa Runnable no;
  3. Un  oggetto che implementa Callable può rilanciare al chiamante una eccezione di tipo checked, mentre un oggetto che implementa Runnable può lanciare soltanto unchecked exceptions.
Vediamo un esempio di utilizzo di Callable.
Per utilizzare un oggetto che implementa un Callable dobbiamo necessariamente utilizzare un ExecutorService.

CALLABLE

import java.util.concurrent.Callable;
public class Fattoriale implements Callable<Long> {
 private long n;
 public Fattoriale(long n){
 this.n=n; 
 }
 @Override
 public Long call() throws Exception {
  
  if(n<=0) throw new Exception("Attenzione inserire un valore positivo!!");
  long f=1;
  for(long i=1;i<=n;i++){
   f*=i;
  }
  return f;
 }
}

EXECUTORSERVICE

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FattorialeTest {
 public static void main(String[] args) throws Exception {
       long N=5;
       Callable<Long> c=new Fattoriale(N);
       ExecutorService es=Executors.newSingleThreadExecutor();
       Future<Long> f=es.submit(c);
       System.out.println(String.format("Il fattoriale di %d è %d",N,f.get()));
       es.shutdown();
 }
}


Si noti che l'executor service funziona anche con oggetti di tipo Runnable ma, poichè questi non tornano un risultato, il Future associato tornerà null se il processo è terminato correttamente.

Generazione numeri casuali

L'utilizzo della classe java.util.Random in un contesto di concorrenza può portare a dei cali di performance e a problemi di contesa delle risorse.
In ambienti multithreaded è preferibile utilizzare la classe

java.util.concurrent.ThreadLocalRandom

introdotta con la java 1.7.

Ad esempio per ottenere un numero causale tra 1 e 10 si può utilizzare il metodo nextInt(int  least,int bound)

Dove la javadoc recita: "Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound (exclusive)", quindi


int n=ThreadLocalRandom.current().nextInt(1, 11);
System.out.println(n);