DEV Community

aristides villarreal
aristides villarreal

Posted on • Edited on

Bases de datos dinámicas con jmoordbcore y MongoDB solo para embebido

La nueva versión de jmoordbcore, soporte especificar el nombre de la base de datos en tiempo de ejecución.

No aplica para entidades que utilizan referencias.

Agregue a su proyecto


 <properties>
   <version.jmoordbcore>1.1.0</version.jmoordbcore> 
 </properties>

<dependency>
  <groupId>com.github.avbravo</groupId>
  <artifactId>jmoordb-core</artifactId>
  <version>${version.jmoordbcore}</version>
</dependency>

<repositories>
 <repository>
    <id>jitpack.io</id>
    <url>https://jitpack.io</url>
  </repository>
</repositories>
Enter fullscreen mode Exit fullscreen mode

Como recordaremos cuando se crea un proyecto que utilice Jmoordbcore se configura en el archivo microprofile-config.properties las propiedades de conexión y bases de datos.

mongodb.uri=mongodb://localhost:27017
#-- Database de configuración
mongodb.jmoordb= configurationjmoordbdb

#-- Database History
mongodb.databasehistory=historydb

#-- Database
mongodb.database=accreditation
mongodb.database1=sft
mongodb.database2=practicadb


Enter fullscreen mode Exit fullscreen mode

Se define una entidad en el paquete model

@Entity
public class Icono {
@Id(autogeneratedActive = AutogeneratedActive.ON)
private Long idicono;
@Column
private String icono;

// set/get constructores
}

Enter fullscreen mode Exit fullscreen mode

Se define un repositorio en el paquete repository

@Repository(entity = Icono.class)
public interface IconoRepository extends CrudRepository<Icono, Long> {

    @Find
    public Optional<Icono> findByIcono(String icono);

    @Lookup
    public List<Icono> lookup(Search search);

    @Count()
    public Long count(Search... search);

       @CountLikeBy(caseSensitive = CaseSensitive.NO, likeByType = LikeByType.ANYWHERE)
    public Long countLikeByIcono(String icono);

    @LikeBy(caseSensitive = CaseSensitive.NO, typeOrder = TypeOrder.ASC, likeByType = LikeByType.ANYWHERE)
    public List<Icono> likeByIcono(String icono);

}

Enter fullscreen mode Exit fullscreen mode

Creamos un endpoint mediante

@Path("icono")
@Tag(name = "Información del icono", description = "End-point para entidad Icono")
@RolesAllowed({"admin"})
public class IconoController {


    // <editor-fold defaultstate="collapsed" desc="Inject">
    @Inject
    IconoRepository iconoRepository;

      @Inject
HistoryRepository historyRepository;


// </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="findAll">
    @GET
    @RolesAllowed({"admin"})
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public List<Icono> findAll() {

        return iconoRepository.findAll();
    }
// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Icono findByIdicono">
    @GET
    @RolesAllowed({"admin"})
    @Path("{idicono}")
    public Icono findByIdicono(
            @Parameter(description = "El idicono", required = true, example = "1", schema = @Schema(type = SchemaType.NUMBER)) @PathParam("idicono") Long idicono) {



        return iconoRepository.findByPk(idicono).orElseThrow(
                () -> new WebApplicationException("No hay icono con idicono " + idicono, Response.Status.NOT_FOUND));

    }
// </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Icono findByIcononame">
    @GET
    @RolesAllowed({"admin"})
    @Path("icononame")


    public Icono findByIcono(@Parameter(description = "El icononame", required = true, example = "1", schema = @Schema(type = SchemaType.STRING)) @QueryParam("icono") final String icono) {



        return iconoRepository.findByIcono(icono).orElseThrow(
                () -> new WebApplicationException("No hay icono con icono " + icono, Response.Status.NOT_FOUND));

    }
//// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="List<Icono> lookup(@QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size)">

    @GET
    @Path("lookup")
    @RolesAllowed({"admin"})

    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public List<Icono> lookup(@QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
        List<Icono> suggestions = new ArrayList<>();
        try {

        Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
        suggestions = iconoRepository.lookup(search);

        } catch (Exception e) {

          MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }

        return suggestions;
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Response save">
    @POST
    @RolesAllowed({"admin"})
    public Response save(
            @RequestBody(description = "Crea un nuevo icono.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Icono.class))) Icono icono) {
iconoRepository.setDynamicDatabase("database1");
  Optional<Icono> iconoOptional=iconoRepository.save(icono);
        if(iconoOptional.isPresent()){
            saveHistory(icono);
               return Response.status(201).entity(iconoOptional.get()).build();
        }else{
              return Response.status(400).entity("Error " + iconoRepository.getJmoordbException().getLocalizedMessage()).build();
        }
    }
// </editor-fold>
    // <editor-fold defaultstate="collapsed" desc="Response update">

    @PUT
    @RolesAllowed({"admin"})
    public Response update(
            @RequestBody(description = "Crea un nuevo icono.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Icono.class))) Icono icono) {


         if(iconoRepository.update(icono)){
             saveHistory(icono);
               return Response.status(201).entity(icono).build();
        }else{
              return Response.status(400).entity("Error " + iconoRepository.getJmoordbException().getLocalizedMessage()).build();
        }
    }
// </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Response delete">
    @DELETE
    @RolesAllowed({"admin"})
    @Path("{idicono}")
    public Response delete(
            @Parameter(description = "El elemento idicono", required = true, example = "1", schema = @Schema(type = SchemaType.NUMBER)) @PathParam("idicono") Long idicono) {
        if(iconoRepository.deleteByPk(idicono) ==0L){
              return Response.status(201).entity(Boolean.TRUE).build();
        }else{
            return Response.status(400).entity("Error " + iconoRepository.getJmoordbException().getLocalizedMessage()).build();
        }
    }
    // </editor-fold>

     // <editor-fold defaultstate="collapsed" desc="Long count(@QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size)">

    @GET
    @Path("count")
    @RolesAllowed({"admin"})


    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public Long count(@QueryParam("filter") String filter, @QueryParam("sort") String sort, @QueryParam("page") Integer page, @QueryParam("size") Integer size) {
       Long result = 0L;
        try {

        Search search = DocumentUtil.convertForLookup(filter, sort, page, size);
        result = iconoRepository.count(search);

        } catch (Exception e) {

          MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }

        return result;
    }

    // </editor-fold>
     // <editor-fold defaultstate="collapsed" desc="private void saveHistory(Icono icono)">

    private void saveHistory(Icono icono){
        try {
                History history = new History.Builder()                 
               .collection("icono")
                    .idcollection(icono.getIdicono().toString())
                                .database("accreditation")
                    .data(icono.toString())
                    .actionHistory(icono.getActionHistory().get(icono.getActionHistory().size()-1)                  )
                     .build();
            historyRepository.save(history);
        } catch (Exception e) {
           ConsoleUtil.error("saveHistory() "+e.getLocalizedMessage());
        }
    }


// </editor-fold>



         // <editor-fold defaultstate="collapsed" desc="Long countLikeByRole(@QueryParam("role") String role)">
    @GET
    @Path("countlikebyicono")
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public Long countLikeByIcono(@QueryParam("icono") String icono) {
        Long result = 0L;
        try {


            result = iconoRepository.countLikeByIcono(icono);

        } catch (Exception e) {

            MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }

        return result;
    }

    // </editor-fold>
      // <editor-fold defaultstate="collapsed" desc="List<Role> likeByRole(@QueryParam("role") String role)">

    @GET
    @Path("likebyicono")
    @RolesAllowed({"admin"})
     @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public List<Icono> likeByIcono(@QueryParam("icono") String icono) {
        List<Icono> suggestions = new ArrayList<>();
        try {


        suggestions = iconoRepository.likeByIcono(icono);

        } catch (Exception e) {

          MessagesUtil.error(MessagesUtil.nameOfClassAndMethod() + "error: " + e.getLocalizedMessage());
        }

        return suggestions;
    }

    // </editor-fold>
}



Enter fullscreen mode Exit fullscreen mode

Cuando se compila la aplicación se genera el código necesario para interactuar desde nuestra aplicación Java con MongoDB.

Cuando deseamos que el nombre de la base de datos no se tome del archivo microprofile-config.properties, podemos definirlo mediante el método .setDynamicDatabase("database"); del repositorio, que asignara el nombre de la base de datos que se pasa como parámetros y tendrá precedencia sobre el archivo de configuración. Tenga presente que se debe asignar a cada método para que sea funcional.

    @POST
    @RolesAllowed({"admin"})
    public Response save(
            @RequestBody(description = "Crea un nuevo icono.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Icono.class))) Icono icono) {
        iconoRepository.setDynamicDatabase("database1");
        Optional<Icono> iconoOptional = iconoRepository.save(icono);
        if (iconoOptional.isPresent()) {
            saveHistory(icono);
            return Response.status(201).entity(iconoOptional.get()).build();
        } else {
            return Response.status(400).entity("Error " + iconoRepository.getJmoordbException().getLocalizedMessage()).build();
        }
    }
Enter fullscreen mode Exit fullscreen mode

Método para buscar todos los documentos se asigna la base de datos.

@GET
@RolesAllowed({"admin"})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public List<Icono> findAll() {
         iconoRepository.setDynamicDatabase("database1");
        return iconoRepository.findAll();
    }

Enter fullscreen mode Exit fullscreen mode

Por el contrario si no se coloca se tomara la base de datos del archivo de configuración.

@GET
@RolesAllowed({"admin"})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

    public List<Icono> findAll() {
       //  iconoRepository.setDynamicDatabase("database1");
        return iconoRepository.findAll();
    }

Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free

AWS GenAI Live!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️