Saltar al contenido

¿Cuál es la diferencia entre MongoTemplate y MongoRepository de Spring Data?

Recuerda que en las ciencias informáticas un error casi siempere suele tener diferentes resoluciones, de igual modo te compartiremos lo más óptimo y eficiente.

Solución:

“Conveniente” y “poderoso de usar” son objetivos contradictorios hasta cierto punto. Los repositorios son mucho más convenientes que las plantillas, pero estas últimas, por supuesto, le brindan un control más detallado sobre qué ejecutar.

Como el modelo de programación del repositorio está disponible para varios módulos de Spring Data, encontrará documentación más detallada en la sección general de los documentos de referencia de Spring Data MongoDB.

TL; DR

Generalmente recomendamos el siguiente enfoque:

  1. Comience con el resumen del repositorio y simplemente declare consultas simples utilizando el mecanismo de derivación de consultas o consultas definidas manualmente.
  2. Para consultas más complejas, agregue métodos implementados manualmente al repositorio (como se documenta aquí). Para el uso de implementación MongoTemplate.

Detalles

Para su ejemplo, esto se vería así:

  1. Defina una interfaz para su código personalizado:

    interface CustomUserRepository 
    
      List yourCustomMethod();
    
    
  2. Agregue una implementación para esta clase y siga la convención de nomenclatura para asegurarse de que podamos encontrar la clase.

    class UserRepositoryImpl implements CustomUserRepository 
    
      private final MongoOperations operations;
    
      @Autowired
      public UserRepositoryImpl(MongoOperations operations) 
    
        Assert.notNull(operations, "MongoOperations must not be null!");
        this.operations = operations;
      
    
      public List yourCustomMethod() 
        // custom implementation here
      
    
    
  3. Ahora deje que su interfaz de repositorio base amplíe la personalizada y la infraestructura utilizará automáticamente su implementación personalizada:

    interface UserRepository extends CrudRepository, CustomUserRepository 
    
    
    

De esta manera, básicamente tienes la opción: todo lo que es fácil de declarar entra en UserRepository, todo lo que está mejor implementado manualmente entra en CustomUserRepository. Las opciones de personalización se documentan aquí.

FWIW, con respecto a las actualizaciones en un entorno de subprocesos múltiples:

  • MongoTemplate proporciona operaciones “atómicas” listas para usarupdateFirst, updateMulti, findAndModify, upsert… que te permiten modificar un documento en una sola operación. los Update objeto utilizado por estos métodos también le permite orientar solo los campos relevantes.
  • MongoRepository solo te da el operaciones CRUD básicasfind, insert, save, delete, que funcionan con POJO que contienen todos los campos. Esto le obliga a actualizar los documentos en varios pasos (1. find el documento a actualizar, 2. modificar los campos relevantes del POJO devuelto, y luego 3. save it), o defina sus propias consultas de actualización a mano usando @Query.

En un entorno de subprocesos múltiples, como por ejemplo, un back-end de Java con varios puntos finales REST, las actualizaciones de método único son el camino a seguir, para reducir las posibilidades de que dos actualizaciones simultáneas sobrescriban los cambios entre sí.

Ejemplo: dado un documento como este: _id: "ID1", field1: "a string", field2: 10.0 y dos subprocesos diferentes actualizándolo simultáneamente …

Con MongoTemplate se vería algo así:

THREAD_001                                                      THREAD_002
|                                                               |
|update(query("ID1"), Update().set("field1", "another string")) |update(query("ID1"), Update().inc("field2", 5))
|                                                               |
|                                                               |

y el estado final del documento es siempre _id: "ID1", field1: "another string", field2: 15.0 ya que cada hilo accede a la base de datos solo una vez y solo se cambia el campo especificado.

Considerando que el mismo escenario de caso con MongoRepository se vería así:

THREAD_001                                                      THREAD_002
|                                                               |
|pojo = findById("ID1")                                         |pojo = findById("ID1")
|pojo.setField1("another string") /* field2 still 10.0 */       |pojo.setField2(pojo.getField2()+5) /* field1 still "a string" */
|save(pojo)                                                     |save(pojo)
|                                                               |
|                                                               |

y el documento final es _id: "ID1", field1: "another string", field2: 10.0 o _id: "ID1", field1: "a string", field2: 15.0 dependiendo de cual save La operación llega al último DB.
(NOTA: Incluso si usamos Spring Data @Version anotación como se sugiere en los comentarios, no cambiaría mucho: uno de los save operaciones arrojarían un OptimisticLockingFailureException, y el documento final seguirá siendo uno de los anteriores, con solo un campo actualizado en lugar de ambos).

Entonces yo diría eso MongoTemplate es una mejor opcion, a menos que tenga un modelo POJO muy elaborado o necesite las capacidades de consultas personalizadas de MongoRepository por alguna razón.

Esta respuesta puede demorarse un poco, pero recomendaría evitar toda la ruta del repositorio. Obtiene muy pocos métodos implementados de gran valor práctico. Para que funcione, se encuentra con la tontería de la configuración de Java en la que puede pasar días y semanas sin mucha ayuda en la documentación.

En su lugar, vaya con el MongoTemplate enrute y cree su propia capa de acceso a datos que lo libere de las pesadillas de configuración que enfrentan los programadores de Spring. MongoTemplate es realmente el salvador para los ingenieros que se sienten cómodos diseñando sus propias clases e interacciones, ya que hay mucha flexibilidad. La estructura puede ser algo como esto:

  1. Crear un MongoClientFactory clase que se ejecutará en el nivel de la aplicación y le dará una MongoClient objeto. Puede implementar esto como Singleton o usando un Enum Singleton (esto es seguro para subprocesos)
  2. Cree una clase base de acceso a datos de la que pueda heredar un objeto de acceso a datos para cada objeto de dominio). La clase base puede implementar un método para crear un objeto MongoTemplate que los métodos específicos de su clase pueden usar para todos los accesos a la base de datos
  3. Cada clase de acceso a datos para cada objeto de dominio puede implementar los métodos básicos o puede implementarlos en la clase base
  4. Los métodos del controlador pueden llamar a métodos en las clases de acceso a datos según sea necesario.

Reseñas y valoraciones del artículo

Nos encantaría que puedieras mostrar este artículo si te valió la pena.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *