Article updated on

Ejemplo Básico de Persistencia con Java

A veces puede que necesitemos sacar nuestros objetos fuera de la RAM  para luego volver a utilizarlos y no perder la información. En lugar de guardar la información del objeto a un archivo y luego volver a instanciar el objeto y repoblarlo con la información guardada, podemos guardar el objeto en sí. A esto en java se conoce como persistencia.

Con java hay muchas maneras de tratar con la persistencia. Hay frameworks que nos pueden facilitar la tarea como por ejemplo Hibernate, Toplink, etc. En este ejemplo se usa la Java Basic Input/Output API contenida en el java.io package.

En java cuando un serializamos un objecto tenemos la garantía de que vamos a poder reconstruirlo después, (ej. queremos grabarlo en un archivo o enviarlo a través de un socket). Para poder serializar un objeto es necesario implementar la interfaz Serializable. Todos los campos del objeto marcados con la palabra transient no se serializarán.

En este ejemplo  se cubren los siguientes temas:

  • Grabar un objeto a un archivo
  • Recuperar el objeto desde archivo.
  • Uso de la palabra clave de java Transient.
  • Uso del interfaz serializable.
  • Uso del serialVersionUID
import java.io.*;
public class SerializationDemo {
    public static void main(String args[]) {
        // Serialización de Objeto 
        try {
            //crea el objecto e imprime sus valores por consola
            MyPojo object1 = new MyPojo("Hello Persisted Object!", -33, 2.72);
            System.out.println("object1: " + object1);
            //crea un fichero para persistir el objeto
            FileOutputStream fos = new FileOutputStream("persisted-object.file");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            //escribe el objeto serializado a un archivo
            oos.writeObject(object1);
            oos.flush();
            oos.close();
        } catch (Exception e) {
            System.out.println("Exception during serialization: " + e);
            System.exit(0);
        }
        // Deserialización de objeto
        try {
            MyPojo object2;
            //abre el archivo
            FileInputStream fis = new FileInputStream("persisted-object.file");
            ObjectInputStream ois = new ObjectInputStream(fis);
            //lee el objeto del archivo
            object2 = (MyPojo) ois.readObject();
            ois.close();
            //imprime los valores del objeto persistido
            System.out.println("object2: " + object2);
            System.out.println("object2 mystring: " +object2.getMyString());
            //saca por pantalla null porque myTransString está marcado como transient
            System.out.println("object2 mystring2: " +object2.getMyTransString());            
        } catch (Exception e) {
            System.out.println("Exception during deserialization: " + e);
            System.exit(0);
        }
    }    
}
//Pojo serializado
class MyPojo implements Serializable {    
    public MyPojo(String mystring, int intVal1, double doubleVal) {
        this.myString = mystring;
        this.intVal1 = intVal1;
        this.doubleVal = doubleVal;
        this.myTransString = "Este valor no se persistirá.";
    }
    //safety ID
    private static final long serialVersionUID = 1234233342333L;
    //campos para persistir
    private String myString;
    private int intVal1;
    private double doubleVal;    
    //campos que no serán persistidos
    private transient String myTransString;
    //getters y setters
    public String getMyString() {
        return myString;
    }
    public void setMyString(String myString) {
        this.myString = myString;
    }
    public String getMyTransString() {
        return myTransString;
    }
    public void setMyTransString(String myTransString) {
        this.myTransString = myTransString;
    }
    public int getIntVal1() {
        return intVal1;
    }
    public void setIntVal1(int intVal1) {
        this.intVal1 = intVal1;
    }
    public double getDoubleVal() {
        return doubleVal;
    }
    public void setDoubleVal(double doubleVal) {
        this.doubleVal = doubleVal;
    }
    //para sacar todos los valores persistibles por pantalla
    @Override
    public String toString() {
        return "mystring=" + myString + "; intVal1=" + intVal1 + "; doubleVal=" + doubleVal;
    }
}

Ejecutar la aplicación

*myString2 es null porque se ha marcado como transient.

MyPojo

  • Es un POJO (Plain Old Java Object) serializado cuyos campos que no sean transient podrán están serializados.
  • myTransString está marcado como transient lo que hace que no sea serializado  y por lo tanto no será persistido.
  • serialVersionUID es un campo de tipo Long de seguridad. Si intentas reconstruir el mismo objeto con un UID diferente saltará una excepción del tipo java.io.InvalidClassException. Esto es útil en caso de que estés compartiendo un objeto entre diferentes aplicaciones, entornos, etc. Si cambias el serialVersionUID cuando cambias el objecto serializado te aseguras de que todos tengan la misma versión.

SerializationDemo class

  • La primera parte crea el fichero y guarda el objeto serializado.
  • La segunda parte deserializa el objeto e imprime sus valores por pantalla.

persisted-object.file

  • Archivo usado para guardar el objecto serializado (persistir). No se guardan los campos marcados como transient.

Notas

  • Una vez que está guardado ya no necesitas la primera parte del SerializationDemo.
  • Si borras la implementacion de la interface  Serializable se lanzará una excepción java.io.NotSerializableException