Páginas

martes, 13 de diciembre de 2016

Primeros pasos con SQLite

Para pequeñas pruebas o arquetipos solemos utilizar una BBDD SQLite, en esta entrada dejo un pequeño trozo de código con algunas de las operaciones mas comunes:
  • Conectar y desconectar de la BBDD
  • Crear y borrar tablas
  • Insertar, actualizar y borrar registros
  • Lanzar diferentes consultas
  • Commit y rollback de transacciones
  • Uso de  PreparedStatement

En el pom.xml de nuestro proyecto deberemos incluir la dependencia:

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>3.15.1</version>
</dependency>

El código sería:

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestSQLite {

 private static final String URL = "jdbc:sqlite:test.db";
 
 public static void main(String[] args) throws SQLException {
  
  final Connection conexion = DriverManager.getConnection(URL);
  final DatabaseMetaData metadatos = conexion.getMetaData();
  System.out.println("------------------------------------------------------------");
  System.out.println("Conectados al motor de BBDD: " + metadatos.getDriverName());
  System.out.println("DriverVersion: " + metadatos.getDriverVersion());
  System.out.println("DatabaseProductVersion: " + metadatos.getDatabaseProductVersion());
  System.out.println("JDBCMajorVersion: " + metadatos.getJDBCMajorVersion());
  
        String sql = "DROP TABLE IF EXISTS CLIENTE;";
        Statement stmt = conexion.createStatement();
        stmt.execute(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Borrada la tabla CLIENTE");
  
        sql = "CREATE TABLE IF NOT EXISTS CLIENTE (ID integer PRIMARY KEY, NOMBRE text NOT NULL, DIRECCION text NOT NULL, PRIORIDAD integer NOT NULL);";
        stmt = conexion.createStatement();
        stmt.execute(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Creada la tabla CLIENTE");
  
  conexion.setAutoCommit(false);
        sql = "INSERT INTO CLIENTE(NOMBRE,DIRECCION,PRIORIDAD) VALUES(?,?,?);";
        PreparedStatement pstmt = conexion.prepareStatement(sql);
        pstmt.setString(1, "cliente1");
        pstmt.setString(2, "direccion1");
        pstmt.setString(3, "1");
        pstmt.executeUpdate();
        pstmt.setString(1, "cliente2");
        pstmt.setString(2, "direccion2");
        pstmt.setString(3, "1");
        pstmt.executeUpdate();
        pstmt.setString(1, "cliente3");
        pstmt.setString(2, "direccion3");
        pstmt.setString(3, "2");
        pstmt.executeUpdate();
        conexion.commit();
  System.out.println("------------------------------------------------------------");
  System.out.println("Insertados 3 registros en tabla CLIENTE");
  
  sql = "SELECT count(*) as NUMREG FROM CLIENTE";
  ResultSet rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados " + rs.getInt("NUMREG") + " registros en tabla CLIENTE");
  
  sql = "SELECT count(*) as NUMREG FROM CLIENTE WHERE NOMBRE ='cliente1'";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados " + rs.getInt("NUMREG") + " registros en tabla CLIENTE con NOMBRE ='cliente1'");
  
  sql = "SELECT count(*) as NUMREG FROM CLIENTE WHERE NOMBRE LIKE 'cliente%'";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados " + rs.getInt("NUMREG") + " registros en tabla CLIENTE con NOMBRE like 'cliente%'");
  
  sql = "SELECT * FROM CLIENTE WHERE PRIORIDAD=1";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados los siguientes registros en tabla CLIENTE con PRIORIDAD=1");
  System.out.println("ID NOMBRE DIRECCION PRIORIDAD");
  while (rs.next()) {
   System.out.println(rs.getInt("ID") + " " + rs.getString("NOMBRE") + " " + rs.getString("DIRECCION") + " " + rs.getInt("PRIORIDAD"));
  }
  
  sql = "UPDATE CLIENTE SET PRIORIDAD=2 WHERE PRIORIDAD=1";
  int numRecAct = stmt.executeUpdate(sql);
  conexion.commit();
  System.out.println("------------------------------------------------------------");
  System.out.println("Actualizados "+numRecAct+" registros de PRIORIDAD=1 a PRIORIDAD=2");
  System.out.println("ID NOMBRE DIRECCION PRIORIDAD");
  
  sql = "SELECT * FROM CLIENTE";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados los siguientes registros en tabla CLIENTE");
  System.out.println("ID NOMBRE DIRECCION PRIORIDAD");
  while (rs.next()) {
   System.out.println(rs.getInt("ID") + " " + rs.getString("NOMBRE") + " " + rs.getString("DIRECCION") + " " + rs.getInt("PRIORIDAD"));
  }
  
  sql = "DELETE FROM CLIENTE WHERE NOMBRE='cliente1'";
  numRecAct = stmt.executeUpdate(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Borrados los registros con NOMBRE='cliente1'");
  
  sql = "SELECT * FROM CLIENTE";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados los siguientes registros en tabla CLIENTE");
  System.out.println("ID NOMBRE DIRECCION PRIORIDAD");
  while (rs.next()) {
   System.out.println(rs.getInt("ID") + " " + rs.getString("NOMBRE") + " " + rs.getString("DIRECCION") + " " + rs.getInt("PRIORIDAD"));
  }
  
  sql = "DELETE FROM CLIENTE";
  numRecAct = stmt.executeUpdate(sql);
  conexion.rollback();
  System.out.println("------------------------------------------------------------");
  System.out.println("Intento cancelado de borrado completo de la tabla CLIENTE");
  
  sql = "SELECT * FROM CLIENTE";
  rs = stmt.executeQuery(sql);
  System.out.println("------------------------------------------------------------");
  System.out.println("Encontrados los siguientes registros en tabla CLIENTE");
  System.out.println("ID NOMBRE DIRECCION PRIORIDAD");
  while (rs.next()) {
   System.out.println(rs.getInt("ID") + " " + rs.getString("NOMBRE") + " " + rs.getString("DIRECCION") + " " + rs.getInt("PRIORIDAD"));
  }
  
  conexion.close();
 }
}

Un saludo

Comparativa librerías JSON: Gson y Jackson

Para manipular datos en formato JSON existen dos librerías: Jackson y Gson. La primera es muy conocida por ser el 'motor' usado por el framework Jersey de Web Services RESTfull, la segunda no lo es tanto.

El presente ejemplo tiene como finalidad comparar el rendimiento de ambas. Tras unas primeras pruebas con POJOS java de diversos tamaños me da la sensación de que Jackson es un poquitín mas rápida.

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

public class TestMotoresJSON {

 private static final int NUMCLIENTES = 5;
 private static final int NUMFACTURAS = 100000;
 
 private static final Gson motorGSON = new GsonBuilder().create();
 private static final ObjectMapper motorJACKSON = new ObjectMapper();
 
 public static void main(String[] args) throws IOException {

  //Montamos un pojo Java con la lista de clientes y facturas
  final List lstClientes = montaListaClientes();

  //Serializo GSon
  long tmp = System.currentTimeMillis();
  String lstClientesJSON = serializoGSon(lstClientes);
  System.out.println("Tiempo serialización GSon:"+(System.currentTimeMillis()-tmp));

  //Deserializo GSon
  tmp = System.currentTimeMillis();
  deserializoGSon(lstClientesJSON);
  System.out.println("Tiempo deserialización GSon:"+(System.currentTimeMillis()-tmp));
  
  //Serializo Prueba
  tmp = System.currentTimeMillis();
  lstClientesJSON = serializoJackson(lstClientes);
  System.out.println("Tiempo serialización Jackson:"+(System.currentTimeMillis()-tmp));
  
  //Deserializo Prueba
  tmp = System.currentTimeMillis();
  deserializoJackson(lstClientesJSON);
  System.out.println("Tiempo deserialización Jackson:"+(System.currentTimeMillis()-tmp));
 }
 
 private static String serializoGSon(final List lstClientes){
   
  return motorGSON.toJson(lstClientes);
 }
 
 private static void deserializoGSon(final String lstClientesJSON){
  
  motorGSON.fromJson(lstClientesJSON, new TypeToken>(){}.getType());
 }
 
 private static String serializoJackson(final List lstClientes) throws IOException {

  return motorJACKSON.writeValueAsString(lstClientes);
 }
 
 private static void deserializoJackson(final String lstClientesJSON) throws IOException {
  
  motorJACKSON.readValue(lstClientesJSON, motorJACKSON.getTypeFactory().constructCollectionType(ArrayList.class, Cliente.class));
 }
 
 private static List montaListaClientes(){
  
  final List lst = new ArrayList();
  Cliente cliente = null;
  Factura fac = null;
  for (int c=0;c());
   for (int f=0;f
Necesitaremos las clases de apoyo:
import java.util.List;

public class Cliente {

 private String CIF;
 private String nombre;
 private String direccion;
 private String email;
 private String telefono;
 private String fax;
 private List facturas;
 
 public String getCIF() {
  return CIF;
 }
 public void setCIF(String cIF) {
  CIF = cIF;
 }
 public String getNombre() {
  return nombre;
 }
 public void setNombre(String nombre) {
  this.nombre = nombre;
 }
 public String getDireccion() {
  return direccion;
 }
 public void setDireccion(String direccion) {
  this.direccion = direccion;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public String getTelefono() {
  return telefono;
 }
 public void setTelefono(String telefono) {
  this.telefono = telefono;
 }
 public String getFax() {
  return fax;
 }
 public void setFax(String fax) {
  this.fax = fax;
 }
 public List getFacturas() {
  return facturas;
 }
 public void setFacturas(List facturas) {
  this.facturas = facturas;
 }
}

public class Factura {

 private String id;
 private String fecha;
 private long bruto;
 private long neto;
 private long iva;
 
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getFecha() {
  return fecha;
 }
 public void setFecha(String fecha) {
  this.fecha = fecha;
 }
 public long getBruto() {
  return bruto;
 }
 public void setBruto(long bruto) {
  this.bruto = bruto;
 }
 public long getNeto() {
  return neto;
 }
 public void setNeto(long neto) {
  this.neto = neto;
 }
 public long getIva() {
  return iva;
 }
 public void setIva(long iva) {
  this.iva = iva;
 }
}

Necesitaremos importar en el pom.xml las dependencias:

     <dependencies>
          <dependency>
               <groupId>com.fasterxml.jackson.core</groupId>
               <artifactId>jackson-databind</artifactId>
               <version>2.8.5</version>
          </dependency>
          <dependency>
               <groupId>com.google.code.gson</groupId>
               <artifactId>gson</artifactId>
               <version>2.6.2</version>
          </dependency>
     </dependencies>

miércoles, 7 de diciembre de 2016

Añadir un fichero nuevo a un fichero zip previamente existente

Hola

Se nos presentó la necesidad de añadir contenido a ciertos ficheros ZIP preexistentes, para abordar el problema podíamos usar la librería Commons Compress de Apache (https://commons.apache.org/proper/commons-compress/) o directamente las clases del paquete 'java.util.zip' del JDK.

El problema es que ambas librerías no añaden contenido a un zip preexistente, sino que sobrescriben el contenido del ZIP original por el nuevo contenido. Debe ser por alguna cuestión 'conceptual' relativa al formato ZIP.

Por tanto la forma de abordar el problema es generar un nuevo fichero zip temopral, volcar en dicho fichero el contenido del fichero zip original, añadir al fichero zip temporal el nuevo fichero, borrar el fichero zip original y renombrar el fichero temporal con el nombre del original.

Ya puestos a documentar el tema, dejo el código con la clase generada:

package org.casa.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class TestZip {

 private static final int BUFFER_SIZE = 1024;

 /**
  * Crea un fichero zip a partir del fichero recibido con el nombre
  * de dicho fichero y extensión zip, el zip se genera en la carpeta
  * que contiene el fichero recibido.
  * 
  * @param fichero
  * @throws IOException
  */
 public static void comprimeFichero(final File fichero) throws IOException {

  //Generamos un fichero zip con nombre del fichero recibido y extensión zip
  final String nombreFichZip = fichero.getName().substring(0, fichero.getName().lastIndexOf("."))+".zip";

  //Creamos el nuevo fichero zip en la ubicación del fichero recibido
  final File zf = new File(fichero.getParentFile()+File.separator+nombreFichZip);
  final FileOutputStream fos = new FileOutputStream(zf);
  final ZipOutputStream zos = new ZipOutputStream(fos);

  //Comprimimos el fichero recibido en el nuevo zip
  final ZipEntry ze = new ZipEntry(fichero.getName());
  zos.putNextEntry(ze);
  final FileInputStream fisEntry = new FileInputStream(fichero);
  copyToZip(fisEntry, zos);

  //Cerramos los manejadores
  fisEntry.close();
  zos.flush();
  zos.closeEntry();
  zos.close();
  fos.close();
 }

 /**
  * Crea un fichero zip con todos los ficheros contenidos en la carpeta
  * recibida, el zip tendrá el nombre del directorio con extensión zip y 
  * se ubicará en el directorio padre del directorio recibido.
  * 
  * @param directorio
  * @throws IOException 
  */
 public static void comprimeDirectorio(final File carpeta) throws IOException {

  //Generamos un fichero zip con nombre de la carpeta recibida y extensión zip
  final String nombreFichZip = carpeta.getName()+".zip";

  //Creamos el nuevo fichero zip en la carpeta padre de la carpeta recibida
  final File zf = new File(carpeta.getParentFile()+File.separator+nombreFichZip);
  final FileOutputStream fos = new FileOutputStream(zf);
  final ZipOutputStream zos = new ZipOutputStream(fos);

  //Comprimimos cada fichero de la carpeta en el nuevo zip
  ZipEntry ze = null;
  FileInputStream fisEntry = null;
  for (final File fich : carpeta.listFiles()) {
   ze = new ZipEntry(fich.getName());
   zos.putNextEntry(ze);
   fisEntry = new FileInputStream(fich);
   copyToZip(fisEntry, zos);
   fisEntry.close();
  }

  //Cerramos los manejadores
  zos.flush();
  zos.closeEntry();
  zos.close();
  fos.close();
 }

 /**
  * Añade un nuevo fichero comprimido al fichero zip recibido por parámetro.
  * 
  * Creamos un zip temporal intermedio donde copiamos el contenido del zip
  * recibido y en este zip temporal añadimos el fichero recibido. Finalmente
  * reemplazamos el fichero zip original con el fichero zip generado.
  * 
  * @param zipFile
  * @param fichero
  * @throws IOException
  */
 public static void addFicheroZip(final File zipFile, final File fichero) throws IOException {

  //Guardamos el nombre y el path del fichero zip recibido
  final String nombreFicheroZip = zipFile.getName();
  final String pathFicheroZip = zipFile.getParent();
  
  //Creamos un nuevo fichero zip temporal en la ubicación del zip recibido
  final File ftemp = File.createTempFile(nombreFicheroZip,null,zipFile.getParentFile());
  final FileOutputStream fostemp = new FileOutputStream(ftemp);
  final ZipOutputStream zostemp = new ZipOutputStream(fostemp);
  
  //Abrimos el fichero zip recibido por parametro
  final FileInputStream fis = new FileInputStream(zipFile);
  final ZipInputStream zis = new ZipInputStream(fis);
  
  //Sacammos el contenido del zip recibido por parametro y lo volcamos al zip temporal
  ZipEntry ze = zis.getNextEntry();
  while (ze!= null) {
   ze.getName();
   zostemp.putNextEntry(ze);
   copyToZip(zis, zostemp);
   ze = zis.getNextEntry();
  }
  
  //Añadimos el fichero nuevo al fichero zip temporal
  final ZipEntry zenuevo = new ZipEntry(fichero.getName());
  zostemp.putNextEntry(zenuevo);
  final FileInputStream fisNuevo = new FileInputStream(fichero);
  copyToZip(fisNuevo, zostemp);

  //Cerramos los manejadores
  fisNuevo.close();
  zis.close();
  fis.close();
  zostemp.flush();
  zostemp.closeEntry();
  zostemp.close();
  fostemp.close();

  //Borramos el fichero zip recibido
  zipFile.delete();
  
  //Renombramos el fichero temporal nuevo
  ftemp.renameTo(new File(pathFicheroZip+File.separator+nombreFicheroZip));
 }

 /**
  * Extrae el contenido del zip recibido por parámetro en la carpeta
  * que contiene el fichero zip recibido.
  * 
  * 
  * @param zipFile
  * @throws IOException
  */
 public static void descomprimeZip(final File zipFile) throws IOException {
  
  //Abrimos el fichero zip recibido por parametro
  final FileInputStream fis = new FileInputStream(zipFile);
  final ZipInputStream zis = new ZipInputStream(fis);

  //Extraemos cada fichero del zip en la carpeta del ZIP recibido
  File fe = null;
  FileOutputStream fose = null;
  ZipEntry ze = zis.getNextEntry();
  while (ze!= null) {
   //Procesamos cada fichero del zip
   fe = new File(zipFile.getParentFile().getCanonicalPath()+File.separator+ze.getName());
   fose = new FileOutputStream(fe);
   copyFromZip(zis, fose);
   fose.flush();
   fose.close();
   //Saltamos al siguiente fichero del zip
   ze = zis.getNextEntry();
  }
  
  //Cerramos los manejadores
  zis.close();
  fis.close();  
 }

 private static void copyToZip(final InputStream is, final ZipOutputStream zos) throws IOException {

  byte[] buffer = new byte[BUFFER_SIZE];
  int length;
  while ((length = is.read(buffer)) >= 0) {
   zos.write(buffer, 0, length);
  }
 }
 
 private static void copyFromZip(final ZipInputStream zis, final OutputStream os) throws IOException {

  byte[] buffer = new byte[BUFFER_SIZE];
  int length;
  while ((length = zis.read(buffer)) >= 0) {
   os.write(buffer, 0, length);
  }
 }
}


Un saludo