Iniziare con jOOQ

1. Introduzione

In questo tutorial, faremo un rapido tour dell'esecuzione di un'applicazione con jOOQ (Java Object Orientated Query). Questa libreria genera classi Java basate sulle tabelle del database e ci consente di creare query SQL indipendenti dai tipi tramite la sua API fluente.

Copriremo l'intera configurazione, la connessione al database PostgreSQL e alcuni esempi di operazioni CRUD.

2. Dipendenze di Maven

Per la libreria jOOQ, avremo bisogno delle seguenti tre dipendenze jOOQ:

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

Avremo anche bisogno di una dipendenza per il driver PostgreSQL:

 org.postgresql postgresql 42.2.16 

3. Struttura del database

Prima di iniziare, creiamo un semplice schema DB per i nostri esempi. Useremo un semplice autore e una relazione articolo :

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. Connessione al database

Ora, diamo un'occhiata a come ci collegheremo al nostro database.

In primo luogo, dobbiamo fornire l'utente, la password e un URL completo al database. Useremo queste proprietà per creare un oggetto Connection utilizzando DriverManager e il suo metodo getConnection :

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

Successivamente, dobbiamo creare un'istanza di DSLContext . Questo oggetto sarà il nostro punto di ingresso per le interfacce jOOQ:

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

Nel nostro caso, stiamo passando il dialetto POSTGRES , ma ce ne sono pochi altri disponibili come H2, MySQL, SQLite e altri.

5. Generazione di codice

Per generare classi Java per le nostre tabelle di database, avremo bisogno del seguente file 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 configurazione personalizzata richiede modifiche nel file sezione in cui inseriamo le credenziali del database e nel file sezione in cui configuriamo il nome del pacchetto e la directory del percorso per le classi che genereremo.

Per eseguire lo strumento di generazione del codice jOOQ, è necessario eseguire il codice seguente:

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

Al termine della generazione, otterremo le due classi seguenti, ciascuna corrispondente alla sua tabella di database:

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

6. Operazioni CRUD

Ora, diamo un'occhiata ad alcune operazioni CRUD di base che possiamo eseguire con la libreria jOOQ.

6.1. Creazione

Innanzitutto, creiamo un nuovo record Articolo . Per fare ciò, dobbiamo richiamare il metodo newRecord con un riferimento di tabella appropriato come parametro:

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

La variabile Article.ARTICLE è un'istanza di riferimento alla tabella del database ARTICLE . È stato creato automaticamente da jOOQ durante la generazione del codice.

Successivamente, possiamo impostare i valori per tutte le proprietà necessarie:

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

Infine, dobbiamo invocare il metodo store sul record per salvarlo nel database:

article.store();

6.2. Lettura

Vediamo ora come leggere i valori dal database. Ad esempio, selezioniamo tutti gli autori:

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

Qui, stiamo usando il metodo select combinato con la clausola from per indicare da quale tabella vogliamo leggere. L'invocazione del metodo fetch esegue la query SQL e restituisce il risultato generato.

L' oggetto Result implementa l' interfaccia Iterable , quindi è facile iterare su ogni elemento. E pur avendo accesso a un singolo record, possiamo ottenere i suoi parametri utilizzando il metodo getValue con un riferimento di campo appropriato:

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); });

Possiamo limitare la query di selezione a un insieme di campi specifici. Recuperiamo solo gli ID e i titoli degli articoli:

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

Possiamo anche selezionare un singolo oggetto con il metodo fetchOne . I parametri per questo sono il riferimento alla tabella e una condizione per abbinare il record corretto.

Nel nostro caso, selezioniamo semplicemente un autore con un id uguale a 1:

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

Se nessun record corrisponde alla condizione, il metodo fetchOne restituirà null .

6.3. In aggiornamento

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();

Il metodo di eliminazione restituirà 1 se l'operazione è riuscita o 0 se l'eliminazione non era necessaria. Ad esempio, quando nulla corrisponde alla condizione.

7. Conclusione

In questo articolo, abbiamo imparato come configurare e creare una semplice applicazione CRUD utilizzando il framework jOOQ. Come al solito, tutto il codice sorgente è disponibile su GitHub.