Empezando con jOOQ

1. Introducción

En este tutorial, haremos un recorrido rápido por la ejecución de una aplicación con jOOQ (consulta orientada a objetos Java). Esta biblioteca genera clases Java basadas en las tablas de la base de datos y nos permite crear consultas SQL seguras a través de su API fluida.

Cubriremos la configuración completa, la conexión de la base de datos PostgreSQL y algunos ejemplos de operaciones CRUD.

2. Dependencias de Maven

Para la biblioteca jOOQ, necesitaremos las siguientes tres dependencias jOOQ:

 org.jooq jooq 3.13.4   org.jooq jooq-meta 3.13.4   org.jooq jooq-codegen 3.13.4 

También necesitaremos una dependencia para el controlador PostgreSQL:

 org.postgresql postgresql 42.2.16 

3. Estructura de la base de datos

Antes de comenzar, creemos un esquema de base de datos simple para nuestros ejemplos. Usaremos una relación simple de Autor y Artículo :

create table AUTHOR ( ID integer PRIMARY KEY, FIRST_NAME varchar(255), LAST_NAME varchar(255), AGE integer ); create table ARTICLE ( ID integer PRIMARY KEY, TITLE varchar(255) not null, DESCRIPTION varchar(255), AUTHOR_ID integer CONSTRAINT fk_author_id REFERENCES AUTHOR );

4. Conexión a la base de datos

Ahora, echemos un vistazo a cómo nos conectaremos a nuestra base de datos.

En primer lugar, debemos proporcionar el usuario, la contraseña y una URL completa a la base de datos. Usaremos estas propiedades para crear un objeto Connection usando DriverManager y su método getConnection :

String userName = "user"; String password = "pass"; String url = "jdbc:postgresql://db_host:5432/baeldung"; Connection conn = DriverManager.getConnection(url, userName, password); 

A continuación, necesitamos crear una instancia de DSLContext . Este objeto será nuestro punto de entrada para las interfaces jOOQ:

DSLContext context = DSL.using(conn, SQLDialect.POSTGRES);

En nuestro caso, estamos pasando el dialecto POSTGRES , pero hay algunos otros disponibles como H2, MySQL, SQLite y más.

5. Generación de código

Para generar clases Java para nuestras tablas de base de datos, necesitaremos el siguiente archivo jooq-config.xml :

   org.postgresql.Driver jdbc:postgresql://db_url:5432/baeldung_database username password   org.jooq.codegen.JavaGenerator  org.jooq.meta.postgres.PostgresDatabase public .*    com.baeldung.jooq.model C:/projects/baeldung/tutorials/jooq-examples/src/main/java   

La configuración personalizada requiere cambios en el sección donde colocamos las credenciales de la base de datos y en la sección en la que configuramos el nombre del paquete y el directorio de ubicación para las clases que generaremos.

Para ejecutar la herramienta de generación de código jOOQ, necesitamos ejecutar el siguiente código:

GenerationTool.generate( Files.readString( Path.of("jooq-config.xml") ) );

Una vez completada la generación, obtendremos las dos clases siguientes, cada una correspondiente a su tabla de base de datos:

com.baeldung.model.generated.tables.Article; com.baeldung.model.generated.tables.Author;

6. Operaciones CRUD

Ahora, echemos un vistazo a algunas operaciones CRUD básicas que podemos realizar con la biblioteca jOOQ.

6.1. Creando

En primer lugar, creemos un nuevo registro de artículo . Para hacerlo, necesitamos invocar el método newRecord con una referencia de tabla adecuada como parámetro:

ArticleRecord article = context.newRecord(Article.ARTICLE);

La variable Article.ARTICLE es una instancia de referencia a la tabla de la base de datos ARTICLE . Fue creado automáticamente por jOOQ durante la generación del código.

A continuación, podemos establecer valores para todas las propiedades necesarias:

article.setId(2); article.setTitle("jOOQ examples"); article.setDescription("A few examples of jOOQ CRUD operations"); article.setAuthorId(1);

Finalmente, necesitamos invocar el método de almacenamiento en el registro para guardarlo en la base de datos:

article.store();

6.2. Leyendo

Ahora, veamos cómo podemos leer valores de la base de datos. Como ejemplo, seleccionemos todos los autores:

Result authors = context.select() .from(Author.AUTHOR) .fetch();

Aquí, estamos usando el método select combinado con la cláusula from para indicar de qué tabla queremos leer. Invocar el método de recuperación ejecuta la consulta SQL y devuelve el resultado generado.

El objeto Result implementa la interfaz Iterable , por lo que es fácil iterar sobre cada elemento. Y mientras tenemos acceso a un solo registro, podemos obtener sus parámetros usando el método getValue con una referencia de campo adecuada:

authors.forEach(author -> { Integer id = author.getValue(Author.AUTHOR.ID); String firstName = author.getValue(Author.AUTHOR.FIRST_NAME); String lastName = author.getValue(Author.AUTHOR.LAST_NAME); Integer age = author.getValue(Author.AUTHOR.AGE); System.out.printf("Author %s %s has id: %d and age: %d%n", firstName, lastName, id, age); });

Podemos limitar la consulta de selección a un conjunto de campos específicos. Busquemos solo los identificadores y títulos de los artículos:

Result
    
      articles = context.select(Article.ARTICLE.ID, Article.ARTICLE.TITLE) .from(Author.AUTHOR) .fetch();
    

También podemos seleccionar un solo objeto con el método fetchOne . Los parámetros para este son la referencia de la tabla y una condición para que coincida con el registro adecuado.

En nuestro caso, simplemente seleccionemos un Autor con una identificación igual a 1:

AuthorRecord author = context.fetchOne(Author.AUTHOR, Author.AUTHOR.ID.eq(1))

Si ningún registro coincide con la condición, el método fetchOne devolverá nulo .

6.3. Actualizando

To update a given record, we can use the update method from the DSLContext object combined with a set method invocations for every field we need to change. This statements should be followed by a where clause with a proper match condition:

context.update(Author.AUTHOR) .set(Author.AUTHOR.FIRST_NAME, "David") .set(Author.AUTHOR.LAST_NAME, "Brown") .where(Author.AUTHOR.ID.eq(1)) .execute();

The update query will run only after we call the execute method. As a return value, we'll get an integer equal to the number of records that were updated.

It's also possible to update an already fetched record by executing its store method:

ArticleRecord article = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1)); article.setTitle("A New Article Title"); article.store();

The store method will return 1 if the operation was successful or 0 if the update was not necessary. For example, nothing was matched by the condition.

6.4. Deleting

To delete a given record, we can use the delete method from the DSLContext object. The delete condition should be passed as a parameter in the following where clause:

context.delete(Article.ARTICLE) .where(Article.ARTICLE.ID.eq(1)) .execute();

The delete query will run only after we call the execute method. As a return value, we'll get an integer equal to the number of deleted records.

It's also possible to delete an already fetched record by executing its delete method:

ArticleRecord articleRecord = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1)); articleRecord.delete();

El método de eliminación devolverá 1 si la operación fue exitosa o 0 si la eliminación no fue necesaria. Por ejemplo, cuando la condición no coincide con nada.

7. Conclusión

En este artículo, hemos aprendido cómo configurar y crear una aplicación CRUD simple usando el marco jOOQ. Como de costumbre, todo el código fuente está disponible en GitHub.