Buscar y actualizar automaticamente

Muchas veces necesitamos incrementar el valor de un campo y retornarlo, por ejemplo para atributos autoincrementable.

Por ejemplo en bases de datos NoSQL como MongoDB no existe el concepto de autoincrementable.

Métodos:

Métodos

Bases de datos NoSQL

public T findOneAndUpdate(String key, String value,String field,Integer... incremento)

MongoDB

public T findOneAndUpdate(Document doc, String field, Integer... incremento)

MongoDB

public T findOneAndUpdate(Document doc, Document inc, Integer... incremento)

MongoDB

Parámetros

Key: es el campo a buscar

value: el valor de ese campo

field: es el campo numérico a implementar

incremento: Opcional si no se pasa ningún valor incrementa en uno el campo

Nota: A partir de la versión 0.2.9 se definió esta clase dentro de JMoordb, no es necesario declarar el entity

Definir el entity: Autoincrementable

@Getter
@Setter
public class Autoincrementable {
  @Id
  private String documento;
  private Integer contador;
  public Autoincrementable() {
  }

 public Autoincrementable(String documento, Integer contador) {
    this.documento = documento;
    this.contador = contador;
 }
  @Override
  public String toString() {
      return "Autoincrementable{" + "documento=" + documento + ", contador=" + contador + '}';
  }
}

Ejemplo 1:

Nota:

Recuerde que no es necesario crear la clase Autoincrementable, este pertenece al framework.

Crear el Repository.

@Stateless
public class AutoincrementableRepository extends AbstractFacade<Autoincrementable> {

    @EJB
    MongoClientProvider mongoClientProvider;
    @Override
    protected MongoClient getMongoClient() {
       return mongoClientProvider.getMongoClient();
    }
    public AutoincrementableFacade(){
        super(Autoincrementable.class,"spardjsd","autoincrementable");
    }
    @Override
    public Object findById(String key, String value) {
       return search(key,value); 
    }
    @Override
    public Object findById(String key, Integer value) {
        return search(key,value);
    }

}

Autoincrementable como campo llave

Contamos con una colección para almacenar facturas, y el atributo idfactura debe incrementarse automáticamente.

  @Getter
  @Setter
  public class Facturas {

  @Id
  private Integer idfactura;
  private Double ventas;

  public Facturas() {
  }

  public Facturas(Integer idfactura, Double ventas) {
      this.idfactura = idfactura;
     this.ventas = ventas;
  }

 @Override
  public String toString() {
      return "Facturas{" + "idfactura=" + idfactura + ", ventas=" + ventas + '}';
  }

 }

Crear una colección para que lleve el contador de los documentos y sus id que se usan en otras colecciones.

Controller

Debemos inicializar el documento Autoincrementable, donde le indicamos el nombre del documento y el contador iniciar para llevar el control. Todos los documentos que se desee controlar su autoincrementable deben ser almacenados aquí. En el ejemplo lo inicializamos en 0.

 public void iniciarAutoicrementable(){
    try {
        Autoincrementable autoincrementable = new Autoincrementable("facturas", 0);
        if(autoincrementableRepository.save(autoincrementable)){
              System.out.println("guardado "); 
        }else{
            System.out.println("no se guardo "+autoincrementableRepository.getException());
        }


    } catch (Exception e) {
        System.out.println("iniciarAutoincrementable() "+e.getLocalizedMessage());

    }
}

Si consultamos el documento

db.autoincrementable.find().pretty()
{ "_id" : ObjectId("58861fdba6cca9146fbb2039"), "documento" : "facturas", "contador" : 0 }

Guardar una factura

public void guardarFactura() {
    try {
        //Busca el contador de facturas, lo incrementa en uno  y devuelve el objeto.
        Autoincrementable autoincrementable = new Autoincrementable();
        autoincrementable = autoincrementableFacade.findOneAndUpdate("documento", "facturas", "contador");
        Integer id = autoincrementable.getContador();

       //Guarda la factura
        Facturas facturas = new Facturas();
        facturas.setIdfactura(id);
        facturas.setVentas(5085.23);
        if (facturasRepository.save(facturas)) {
            System.out.println("guardado");
        } else {
            System.out.println("No se guardo " + facturasRepository.getException());
        }

    } catch (Exception e) {
        System.out.println("guardarFactura() " + e.getLocalizedMessage());
    }
}

Si consultamos la colección autoincrementable, podemos comprobar que se consulto el documento facturas y automáticamente se incremento en uno el valor del contador.

db.autoincrementable.find().pretty()                                                            
{
    "_id" : ObjectId("58861fdba6cca9146fbb2039"),
    "documento" : "facturas",
    "contador" : 1   
}

Si consultamos la colección facturas

db.facturas.find().pretty()                                                     
{
    "_id" : ObjectId("58863489a6cca91a36d27b3a"),
    "idfactura" : 1,
    "ventas" : 5085.23
}

Ejemplo 2:

Autoincremantable en un atributo que no es llave primaria.

En el método save() , verificamos si no se ha creado un registro autoincrementable y lo creamos.

//verifica si no se ha creado el contador para proveedor
            Optional<Autoincrementable> autoincrementableOptional = autoincrementableRepository.find(new Document("documento", "proveedor"));
            if (!autoincrementableOptional.isPresent()) {

                Autoincrementable autoincrementable = new Autoincrementable("proveedor", 0);
                if (autoincrementableFacade.save(autoincrementable)) {
                }
            }

        Autoincrementable autoincrementable = new Autoincrementable();
        autoincrementable = autoincrementableRepository.findOneAndUpdate("documento", "proveedor", "contador");
        Integer id = autoincrementable.getContador();
        proveedor.setAutoincrementable(id);
            if (proveedorRepository.save(proveedor)) {
                JsfUtil.successMessage(rf.getAppMessage("info.save"));
                reset();
            } else {
                JsfUtil.successMessage("save() " + proveedorFacade.getException().toString());
            }

Análisis de autoincrementables

Ejemplo del porque se implementa findOneAndUpdate()

Existe una colección de documentos donde se maneja un campo entero que funcionara como autoincrementable:

Agenda{"Id":1,"evento":"A"},

  {"Id":2,"evento":"B"},

  {"Id":3,"evento":"C"}

Si se elimina el evento 3,

Agenda{"Id":1,"evento":"A"},

   {"Id":2,"evento":"B"}

Cuando se desee insertar un documento con el {"evento":"D"}, se pueden producir algunas situaciones

*_1. Utilizar la función count() *_para conocer la cantidad de documentos que tiene la colección, este devolverá 2 y al sumarle 1 tendrá el valor de 3, que ya fue usado para el {"evento":"C"}. Al insertarlo quedaría de la siguiente manera:

Agenda

   {"Id":1,"evento":"A"},

   {"Id":2,"evento":"B"},

    {"Id":3,"evento":"D"}

2. Si buscamos el ultimo documento de la colección{"Id":2,"evento":"B"} , el valor del id es 2 al sumarle 1 quedara en 3, por lo tanto al insertar el evento {"evento":"D"} a la colección este tendría el valor de 3 para el id y este ya fue usado en el {"evento" :"C"}.

Al insertarlo quedaría de la siguiente manera:

Agenda{"Id":1,"evento":"A"},

    {"Id":2,"evento":"B"},

    {"Id":3,"evento":"D"}

De esta manera en la colección Agenda utilizara el valor que devuelva el campo valor de la colección

Autoincrementable.

El método findOneAndUpdate() busca el documento que cumpla la condición y realiza el incremento automático y devuelve el documento actualizado.

// incrementa en 1 el campo Valor

findOneAndUpdate("documento", "agenda", "valor");

// incrementa en 8 el campo Valor, le podemos indicar el valor que deseamos de incremento

findOneAndUpdate("documento", "agenda", "valor",8);

Al insertarlo quedaría de la siguiente manera:

Incrementa el campo valor y devuelve el documento actualizadoAutoincrementable{"documento":"agenda","valor":4}

y este se asigna al id de la colección Agenda Agenda

     {"Id":1,"evento":"A"}

     {"Id":2,"evento":"B"}

     {"Id":4,"evento":"D"}**

Código en Java:

Autoincrementable autoincrementable = new Autoincrementable();

autoincrementable=autoincrementableRepository.findOneAndUpdate("documento", "agenda", "valor");

agenda.setIdagenda(autoincrementable.getValor());

Last updated