8. Transacciones


Probablemente se habra preguntado como maneja db4o accesos concurrentes a una misma base de datos. Al igual que cualquier otra DBMS, db4o provee un mecanismo de transacciones. Antes de ver como multiples clientes, tal vez hasta remotos, acceden a una instancia de db4o en paralelo, vamos a hacer una introduccion a los conceptos de transaccion.


    8.1. Cometer y deshacer


    Tal vez no lo haya notado, pero ya hemos estado trabajando con transacciones desde el primer capitulo. Por definicion, siempre se trabaja dentro de una transaccion cuando se interactua con db4o. Una transaccion es creada implicitamente cuando se abre un contenedor, y la transaccion actual es implicitamente cometida cuando lo cierra. Asi entonces el pedazo de codigo siguiente que almacena un auto es semanticamente identico a los que hemos visto, simplemente que hace la cometida explicita.


    [storeCarCommit]
    Pilot pilot=new Pilot("Rubens Barrichello",99);
    Car car=new Car("BMW");
    car.setPilot(pilot);
    db.set(car);
    db.commit();



    [listAllCars]
    ObjectSet result=db.get(new Car(null));
    listResult(result);


    Sin embargo, tambien podemos deshacer la transaccion actual, reiniciando el estado de nuestra base de datos al punto de la ultima cometeada.


    [storeCarRollback]
    Pilot pilot=new Pilot("Michael Schumacher",100);
    Car car=new Car("Ferrari");
    car.setPilot(pilot);
    db.set(car);
    db.rollback();



    [listAllCars]
    ObjectSet result=db.get(new Car(null));
    listResult(result);



    8.2. Refrescando objetos vivos


    Sin embargo hay un problema: Podemos volver nuestra base de datos a un estado anterior, pero esto no desencadena automagicamente lo mismo para nuestros objetos vivos.


    [carSnapshotRollback]
    ObjectSet result=db.get(new Car("BMW"));
    Car car=(Car)result.next();
    car.snapshot();
    db.set(car);
    db.rollback();
    System.out.println(car);


    Debemos refrescar nuestros objetos vivos explicitamente cuando sospechamos que han podido ser parte de una transaccion deshecha.


    [carSnapshotRollbackRefresh]
    ObjectSet result=db.get(new Car("BMW"));
    Car car=(Car)result.next();
    car.snapshot();
    db.set(car);
    db.rollback();
    db.ext().refresh(car,Integer.MAX_VALUE);
    System.out.println(car);


    Para que sirve entonces la construccion ExtObjectContainer ? Bueno, provee algo de funcionalidad estable, pero la API puede estar sujeta a cambios. En cuanto nos aseguremos que no habra mas cambios, la funcionalidad de ext sera transferida a la API comun de ObjectContainer. Cubriremos la funcionalidad extendida en mas detalle en un capitulo posterior.

    Finalmente, limpiamos todo de nuevo.


    [deleteAllObjects]
    ObjectSet result=db.get(new Object());
    while(result.hasNext()) {
        db.delete(result.next());
    }



    8.3. Conclusión


    Hemos visto como funcionan las transacciones para un colo cliente. En el próximo capítulo veremos como el concepto de transacción se extiende a múltiples clientes, así estén dentro de la misma VM o en una máquina remota.


    8.4. Fuente completo



    package com.db4o.f1.chapter5;

    import java.io.*;
    import com.db4o.*;
    import com.db4o.f1.*;


    public class TransactionExample extends Util {
        public static void main(String[] args) {
            new File(Util.YAPFILENAME).delete();
            ObjectContainer db=Db4o.openFile(Util.YAPFILENAME);
            try {
                storeCarCommit(db);
                db.close();
                db=Db4o.openFile(Util.YAPFILENAME);
                listAllCars(db);
                storeCarRollback(db);
                db.close();
                db=Db4o.openFile(Util.YAPFILENAME);
                listAllCars(db);
                carSnapshotRollback(db);
                carSnapshotRollbackRefresh(db);
                deleteAllObjects(db);
            }
            finally {
                db.close();
            }
        }
        
        public static void storeCarCommit(ObjectContainer db) {
            Pilot pilot=new Pilot("Rubens Barrichello",99);
            Car car=new Car("BMW");
            car.setPilot(pilot);
            db.set(car);
            db.commit();
        }

        public static void listAllCars(ObjectContainer db) {
            ObjectSet result=db.get(new Car(null));
            listResult(result);
        }
        
        public static void storeCarRollback(ObjectContainer db) {
            Pilot pilot=new Pilot("Michael Schumacher",100);
            Car car=new Car("Ferrari");
            car.setPilot(pilot);
            db.set(car);
            db.rollback();
        }

        public static void deleteAllObjects(ObjectContainer db) {
            ObjectSet result=db.get(new Object());
            while(result.hasNext()) {
                db.delete(result.next());
            }
        }

        public static void carSnapshotRollback(ObjectContainer db) {
            ObjectSet result=db.get(new Car("BMW"));
            Car car=(Car)result.next();
            car.snapshot();
            db.set(car);
            db.rollback();
            System.out.println(car);
        }

        public static void carSnapshotRollbackRefresh(ObjectContainer db) {
            ObjectSet result=db.get(new Car("BMW"));
            Car car=(Car)result.next();
            car.snapshot();
            db.set(car);
            db.rollback();
            db.ext().refresh(car,Integer.MAX_VALUE);
            System.out.println(car);
        }
    }





    --
    generated by
    Doctor courtesy of db4objecs Inc.