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 autosufficente 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
A differenza della versione precedente ( descritta qui ) questa versione permette di importare/esportare anche tabelle che hanno vincoli di integrità relazionale.
Per fare questo disabilita il check delle Costraint , esegue l’intera importazione all’interno di una transazione, e poi le riattiva.
Questo comportamento può essere attivato con checkConstraint=false
Il comportamento di default è identico alla versione precedente
il file può essere scaricato da QUI
vediamo un esempio di utilizzo:
package cavia;
import darshan.util.MysqlBackup;
public class Main {
public static void main(String[] args) {
MysqlBackup b= new MysqlBackup("127.0.0.1", "3306", "root", "root", "darshan");
b.checkConstraint=false;
b.all_to_zip("/home/darshan/Scrivania/post/dump.zip");
System.out.println("Done");
}
la classe viene istanziata con MysqlBackup(ip, porta, user, password, database) , poi con b.checkConstraint=false; disabilito il check delle costraint e con all_to_zip eseguo il dump in un file zip, per le altre funzioni affidatevi al javadoc che trovate anche qui
di seguito il sorgente
package darshan.util;
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
* @version 2.0
* 14/06/2011
* http://www.thedarshan.com
*/
public class MysqlBackup {
private static String head="SET AUTOCOMMIT=0; SET FOREIGN_KEY_CHECKS=0;\n";
private static String tail="SET FOREIGN_KEY_CHECKS=1;COMMIT;SET AUTOCOMMIT=1;\n";
/**
* permette di abilitare/disabilitare il controllo dell'integrità referenziale
* durante la fase di creazione, nel caso sia disabilitata è possibile inserire
* tabelle che hanno riferimenti in qualsiasi ordine.
*/
public boolean checkConstraint=true;
private String host, port, user,password, db;
/**
* boolean installed()
* verifica se è possibile avviare mysqldump,<br>
* 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));
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, <br> 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 <br>
* è un overload
*/
private String getData(String host, String port, String user,
String password, String db) throws Exception{
return getData(host, port, user, password, db,null);
}
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));
StringBuilder temp = new StringBuilder();
DataOutputStream output=new DataOutputStream(stream);
String buffer;
if(!checkConstraint)output.writeBytes(head);
while ((buffer = br.readLine()) != null) {
if(stream!=null){
output.writeBytes(buffer+"\n");
}else{
temp.append(buffer).append("\n");
}
}
if(!checkConstraint)output.writeBytes(tail);
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));
StringBuilder temp = new StringBuilder();
String buffer;
while ((buffer = br.readLine()) != null) {
temp.append(buffer).append("\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 <BR>
* 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: <br>
* data.sql con i dati <br>
* 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;
}
}
3 commenti
No ping yet
Antonio scrive:
3 novembre 2011 a 18:47 (UTC 2)
Ciao Vincenzo, sto provando ad utilizzare la tua classe, ma avendo un Mac non riesco a trovare il programma mysqldump.exe hai idea di come posso aggirare la cosa?
Vincenzo La Spesa scrive:
7 novembre 2011 a 15:20 (UTC 2)
mmm, non ho mai toccato un Mac per più di 10 minuti di fila… provo a chiedere ai miei contatti xD
Vincenzo La Spesa scrive:
10 novembre 2011 a 03:01 (UTC 2)
Dunque, intanto non devi cercare mysqldump.exe ma semplicemente mysqldump, se lo chiami da terminale lo trova? o non l’hai proprio installato? se è installato basta un which mysqldump per sapere dove si trova