# 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**

![](https://1490144122-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lc1Wg6bBVlJX-GjApa1%2F-Lc1WhtDA-TTmZ6My9OJ%2F-Lc1WvizwF11F91bYfqc%2Fauto.png?generation=1554820620675944\&alt=media)

**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:**&#x20;

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 actualizado**Autoincrementable{"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());
```
