«

»

feb 25

Una classe Java per effettuare il backup di un database Mysql

Quando si sviluppa un applicazione che permette di interagire e modificare un database  può essere utile prevedere una funzione che permetta di effettuare velocemente e con un solo click il backup completo dell’intero database (dati, struttura, trigger e stored procedure).

Questa classe fa esattamente questo, e a differenza dei molti snippet che si trovano sul web è completa e autosufficiente e documentata con javadoc, necessita soltanto della presenza nel sistema del comando “mysqldump” (presenza che viene verificata dalla classe stessa).

La classe avvia un istanza di mysqldump e permette di salvarne l’output in dei file di testo ,in un unico file zip o eventualmente in una stringa

Spero solo che questo codice non finisca schiaffato in qualche forum che non linka nemmeno il sito, fosse per me estenderei il 41bis ai succhiatori di codice

ecco il link per il download [MysqlBackup.java] Questa versione è obsoleta, fare riferimento alla versione descritta QUI
di seguito il sorgente

package gestoredb;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 *
 * @author Vicenzo La Spesa
 * http://thedarshan.wordpress.com
 * "Il backup è quella cosa totalmente inutile finché non serve"
 */
public class MysqlBackup {
private String host, port, user,password, db;

 /**
  * boolean installed()
  * verifica se è possibile avviare mysqldump,
  * La verifica viene effettuata avviando "mysqldump --help" e cercando la stringa
  * "mysqldump al suo interno"
  * @return true se il comando è disponibile, false altrimenti
  */
 public boolean installed(){
        try {
            Process run = Runtime.getRuntime().exec("mysqldump --help");
            InputStream in = run.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            StringBuffer temp = new StringBuffer();
            String out = br.readLine();
            int n=out.indexOf("mysqldump");
            br.close();
            in.close();
            if(n >-1 && n<2) return true;
        } catch (IOException ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
        }
    return false;
 }

 /**
  * @param host
  * @param port
  * @param user
  * @param password
  * @param db
  * @return una stringa con il backup del database,
 una stringa vuota se scrive sullo stream
  * @throws java.lang.Exception
  *
  * esegue il backup dei dati su stringa,o su uno stream dato come argomento
  * è un overload
  */
 static private String getData(String host, String port, String user,
                        String password, String db) throws Exception{
     return getData(host, port, user, password, db,null);

 }
 static private String getData(String host, String port, String user,
                        String password, String db, OutputStream stream) throws Exception {
  Process run = Runtime.getRuntime().exec(
                       "mysqldump --host=" + host + " --port=" + port +
                       " --user=" + user + " --password=" + password +
                       " --compact --complete-insert --extended-insert " +
                       "--skip-comments --skip-triggers " + db);
  InputStream in = run.getInputStream();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  StringBuffer temp = new StringBuffer();
  DataOutputStream output=new DataOutputStream(stream);

  String buffer;

  while ((buffer = br.readLine()) != null) {
      if(stream!=null){
            output.writeBytes(buffer+"\n");
      }else{
            temp.append(buffer+"\n");
      }

  }

  br.close();
  in.close();

  return temp.toString();//se scrive sullo stream è una stringa vuota
 }

 /**
  *
  * @param host
  * @param port
  * @param user
  * @param password
  * @param db
  * @return una stringa con la struttura del db
  * @throws java.lang.Exception
  *
  * estrae la struttura del db e le stored procedure
  */
 static private String getRoutine(String host, String port, String user,
                           String password, String db) throws Exception {
  Process run = Runtime.getRuntime().exec(
                       "mysqldump --host=" + host + " --port=" + port +
                       " --user=" + user + " --password=" + password +
                       " --compact --no-create-info " +
                       "--no-data --routines " + db);
  InputStream in = run.getInputStream();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));

  StringBuffer temp = new StringBuffer();

  String buffer;

  while ((buffer = br.readLine()) != null) {
            temp.append(buffer+"\n");
      }

  br.close();
  in.close();

  return temp.toString();
 }

    public MysqlBackup(String host, String port, String user,
                           String password, String db) {
        this.host=host;
        this.port=port;
        this.user=user;
        this.password=password;
        this.db=db;
    }

    /**
     * @throws java.lang.Exception
     *
     * Wrapper di getData
     * <strong>
     * LA FUNZIONE NON È OTTIMIZZATA E ALLOCA MOLTA RAM
* SERVE SOLO PER FARE TEST
     * </strong>
     */
    public String data_to_string() throws Exception{
        return getData(host, port, user, password, db);
    }

    /**
     *
     * Wrapper di getRoutine()
     * @throws java.lang.Exception
     */
    public String routine_to_string() throws Exception{
        return getRoutine(host, port, user, password, db);
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * Scrive i dati su un file, funzione ottimizzata per allocare meno ram
     */
    public boolean data_to_file(String nomefile) {
        File filedst = new File(nomefile);
        try {
            FileOutputStream dest = new FileOutputStream(filedst);
            getData(host, port, user, password, db, dest);
            dest.flush();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * Scrive i dati su un file
     */
    public boolean routine_to_file(String nomefile){
        File filedst = new File(nomefile);
        try {
            FileOutputStream dest = new FileOutputStream(filedst);
            dest.write(routine_to_string().getBytes());
            dest.flush();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }

    /**
     *
     * @param nomefile
     * @return true se va bene, false altrimenti
     * genera un file zip con all'interno due files:
     * data.sql con i dati
     * routine.sql con la struttura e le procedure
     */

    public boolean all_to_zip(String nomefile){
        try {
            File filedst = new File(nomefile);
            FileOutputStream dest = new FileOutputStream(filedst);
            ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(dest));
            zip.setMethod(ZipOutputStream.DEFLATED);
            zip.setLevel(Deflater.BEST_COMPRESSION);
            zip.putNextEntry(new ZipEntry("data.sql"));
            getData(host, port, user, password, db, zip);
            zip.putNextEntry(new ZipEntry("routine.sql"));
            zip.write(routine_to_string().getBytes());
            zip.close();
            dest.close();
        } catch (Exception ex) {
            Logger.getLogger(MysqlBackup.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        return true;
    }
}
Share Button

8 comments

Vai al modulo dei commenti

  1. ADriano

    E se invece di un file zip volessi avere solo il file data.sql?

    Cosa dovrei modificare?

  2. thedarshan

    non devi modificare nulla, devi usare la funzione data_to_file(String nomefile).

    includi l’intera classe nel progetto e usi le funzioni che ti servono

  3. melmar

    ho provato ad utilizzare la tua classe, ma sempre la stessa eccezione : “Cannot run program “mysqldump””

  4. thedarshan

    assicurati che mysqldump sia installato e sia nel path.

    di solito viene installato insieme al server

  5. melmar

    è installato, adesso mi hai fatto venire alcuni dubbi sul path. In che cartella dovrebbe essere?

  6. thedarshan

    deve essere o nella directory corrente o in una delle directory specificate nella variabile d’ambiente path.

    per visualizzare la variabile path da una shell di dos puoi usare “SET PATH”

    per modificarla da terminale francamente non lo so, windows xp e superiori non usano il file autoexec.bat o autoexec.nt

    ti consiglio di cliccare col sinistro su risorse del computer e poi fare

    Proprietà
    Avanzate
    Variabili d’ambiente

    si trova tra le variabili di sistema

  7. giuseppe

    ciao ho provato ad usare la tua classe, ma ho notato che quando creo il file zip, l’annesso file .sql non contiene solo i dati (ovvero solo le istruzioni INSERT) ma l’intera struttura del db.

    Ora la domanda è :
    è possibile creare solo uno script senza la struttura del db??

    Grazie mille e complimenti

    1. thedarshan

      dovrebbe essere possibile aggiungendo i flag
      “–no-create-db –no-create-info” alla riga 74

      http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html

Commenti disabilitati.