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.