Úvod do Jooq s jarou

1. Prehľad

Tento článok predstaví Jooq objektovo orientované dopytovanie - Jooq - a jednoduchý spôsob jeho nastavenia v spolupráci s jarným rámcom.

Väčšina aplikácií Java má akýsi druh vytrvalosti SQL a pristupuje k tejto vrstve pomocou nástrojov na vyššej úrovni, ako je JPA. A aj keď je to užitočné, v niektorých prípadoch skutočne potrebujete jemnejší a jemnejší nástroj, aby ste sa dostali k svojim údajom alebo skutočne využili všetko, čo základná databáza ponúka.

Jooq sa vyhýba niektorým typickým vzorom ORM a generuje kód, ktorý nám umožňuje vytvárať typicky bezpečné dotazy a získať úplnú kontrolu nad vygenerovaným SQL prostredníctvom čistého a výkonného plynulého rozhrania API.

Tento článok sa zameriava na jarné MVC. Náš článok Podpora Spring Boot pre jOOQ popisuje, ako používať jOOQ v Spring Boot.

2. Maven závislosti

Na spustenie kódu v tomto tutoriále sú potrebné nasledujúce závislosti.

2.1. JOOQ

 org.jooq jooq 3.2.14 

2.2. Jar

Pre náš príklad je potrebných niekoľko jarných závislostí; aby sme to však zjednodušili, musíme do súboru POM explicitne zahrnúť dva z nich:

 org.springframework spring-context 5.2.2.RELEASE org.springframework spring-jdbc 5.2.2.RELEASE 

2.3. Databáza

Na uľahčenie nášho príkladu využijeme zabudovanú databázu H2:

 com.h2database h2 1.4.191 

3. Generovanie kódu

3.1. Štruktúra databázy

Poďme si predstaviť štruktúru databázy, s ktorou budeme v tomto článku pracovať. Predpokladajme, že potrebujeme vytvoriť databázu pre vydavateľa na ukladanie informácií o knihách a autoroch, ktorých spravuje, kde môže autor napísať veľa kníh a na knihe sa môže spolupodieľať veľa autorov.

Aby sme to zjednodušili, vygenerujeme iba tri tabuľky: kniha za knihy, autor pre autorov a ďalšia tabuľka s názvom autor_kniha reprezentovať vzťah medzi mnohými autormi a knihami. The autor tabuľka má tri stĺpce: id, krstné menoa priezvisko. The kniha tabuľka obsahuje iba a titul stĺpec a id primárny kľúč.

Nasledujúce dotazy SQL uložené v intro_schema.sql zdrojový súbor, bude vykonaný proti databáze, ktorú sme už predtým nastavili, aby sme vytvorili potrebné tabuľky a vyplnili ich vzorovými údajmi:

DROP TABUĽKA AK EXISTUJE autor_kniha, autor, kniha; CREATE TABLE autor (id INT NOT NULL PRIMARY KEY, first_name VARCHAR (50), last_name VARCHAR (50) NOT NULL); CREATE TABLE book (id INT NOT NULL PRIMARY KEY, title VARCHAR (100) NOT NULL); CREATE TABLE author_book (author_id INT NOT NULL, book_id INT NOT NULL, PRIMARY KEY (author_id, book_id), CONSTRAINT fk_ab_author FOREIGN KEY (author_id) REFERENCES autor (id) AKTUALIZOVAŤ KASKÁDU NA VYMAZAŤ KASKÁDU, CONSTRAINT fk_ab (id)); INSERT INTO autor VALUES (1, 'Kathy', 'Sierra'), (2, 'Bert', 'Bates'), (3, 'Bryan', 'Basham'); INSERT INTO book VALUES (1, 'Head First Java'), (2, 'Head First Servlets and JSP'), (3, 'OCA / OCP Java SE 7 Programmer'); INSERT INTO author_book VALUES (1, 1), (1, 3), (2, 1);

3.2. Vlastnosti Maven Plugin

Na vygenerovanie kódu Jooq použijeme tri rôzne doplnky Maven. Prvým z nich je doplnok Properties Maven.

Tento doplnok sa používa na čítanie konfiguračných údajov zo súboru prostriedkov. Nie je to potrebné, pretože údaje môžu byť priamo pridané do POM, ale je dobré spravovať vlastnosti externe.

V tejto časti definujeme vlastnosti pre databázové pripojenia vrátane triedy ovládača JDBC, adresy URL databázy, používateľského mena a hesla v súbore s názvom intro_config.properties. Externalizácia týchto vlastností uľahčuje prepínanie databázy alebo iba zmenu konfiguračných údajov.

The read-project-properties cieľ tohto doplnku by mal byť viazaný na počiatočnú fázu, aby bolo možné pripraviť konfiguračné údaje na použitie inými doplnkami. V takom prípade je viazaný na inicializovať fáza:

 org.codehaus.mojo properties-maven-plugin 1.0.0 inicializuje vlastnosti read-project-src / main / resources / intro_config.properties 

3.3. Doplnok SQL Maven

Plugin SQL Maven sa používa na vykonávanie príkazov SQL na vytváranie a vyplňovanie databázových tabuliek. Využije vlastnosti, ktoré boli extrahované z intro_config.properties súbor pomocou pluginu Properties Maven a prevezmite príkazy SQL z intro_schema.sql zdroj.

Doplnok SQL Maven je nakonfigurovaný takto:

 org.codehaus.mojo sql-maven-plugin 1.5 initialize execute $ {db.driver} $ {db.url} $ {db.username} $ {db.password} src / main / resources / intro_schema.sql com.h2database h2 1.4.191 

Upozorňujeme, že tento doplnok musí byť umiestnený neskôr ako doplnok Properties Maven v súbore POM, pretože ich ciele vykonávania sú viazané na rovnakú fázu a Maven ich vykoná v poradí, v akom sú uvedené.

3.4. jOOQ doplnok Codegen

Plugin Jooq Codegen generuje kód Java zo štruktúry databázovej tabuľky. Jeho generovať cieľ by mal byť viazaný na generovať zdroje fázy na zabezpečenie správneho poradia vykonania. Metadáta doplnku vyzerajú takto:

 org.jooq jooq-codegen-maven $ {org.jooq.version} generate-sources generate $ {db.driver} $ {db.url} $ {db.username} $ {db.password} com.baeldung.jooq. úvod.db src / main / java 

3.5. Generuje sa kód

Aby sme dokončili proces generovania zdrojového kódu, musíme spustiť Maven generovať zdroje fáza. V Eclipse to môžeme urobiť tak, že klikneme pravým tlačidlom myši na projekt a vyberieme Spustiť ako –>Generovať zdroje. Po dokončení príkazu zdrojové súbory zodpovedajúce autor, kniha, autor_kniha sú generované tabuľky (a niekoľko ďalších pre podporné triedy).

Poďme sa prehrabať v tabuľkových triedach a zistiť, čo Jooq vytvoril. Každá trieda má statické pole s rovnakým názvom ako trieda, okrem toho, že všetky písmená v názve sú veľké. Nasledujú útržky kódu prevzaté z definícií generovaných tried:

The Autor trieda:

public class Autor rozširuje TableImpl {public static final Autor AUTHOR = nový Autor (); // ostatní členovia triedy}

The Kniha trieda:

public class Book extends TableImpl {public static final Book BOOK = new Book (); // ostatní členovia triedy}

The Autorská kniha trieda:

public class AuthorBook rozširuje TableImpl {public static final AuthorBook AUTHOR_BOOK = new AuthorBook (); // ostatní členovia triedy}

Inštancie, na ktoré tieto statické polia odkazujú, budú slúžiť ako objekty prístupu k údajom, ktoré budú predstavovať zodpovedajúce tabuľky pri práci s inými vrstvami v projekte.

4. Konfigurácia pružiny

4.1. Preklady výnimiek jOOQ na jar

Aby boli výnimky vyvolané vykonaním Jooq konzistentné s jarnou podporou prístupu do databázy, musíme ich preložiť do podtypov DataAccessException trieda.

Definujme implementáciu ExecuteListener rozhranie na prevod výnimiek:

public class ExceptionTranslator extends DefaultExecuteListener {public void exception (ExecuteContext context) {SQLDialect dialect = context.configuration (). dialect (); SQLExceptionTranslator translator = nový SQLErrorCodeSQLExceptionTranslator (dialect.name ()); context.exception (prekladač .translate ("Prístup k databáze pomocou Jooq", context.sql (), context.sqlException ())); }}

Túto triedu bude používať kontext jarnej aplikácie.

4.2. Konfigurácia jari

Táto časť bude obsahovať kroky na definovanie a PersistenceContext , ktorý obsahuje metadáta a fazuľa, ktoré sa majú použiť v kontexte jarnej aplikácie.

Začnime aplikovaním potrebných anotácií na triedu:

  • @ Konfigurácia: Urobte triedu tak, aby bola rozpoznaná ako nádoba na fazuľu
  • @ComponentScan: Konfigurácia smerníc na skenovanie vrátane hodnotu možnosť deklarovať pole mien balíkov na hľadanie komponentov. V tomto výučbe je hľadaný balík vygenerovaný doplnkom Jooq Codegen Maven
  • @EnableTransactionManagement: Povoliť správu transakcií do jari
  • @PropertySource: Uveďte umiestnenie súborov vlastností, ktoré sa majú načítať. Hodnota v tomto článku ukazuje na súbor obsahujúci konfiguračné údaje a dialekt databázy, ktorý je zhodne ten istý súbor uvedený v pododdiele 4.1.
@Configuration @ComponentScan ({"com.baeldung.Jooq.introduction.db.public_.tables"}) @EnableTransactionManagement @PropertySource ("classpath: intro_config.properties") verejná trieda PersistenceContext {// ďalšie deklarácie}

Ďalej použite znak Životné prostredie objekt, aby získal konfiguračné údaje, ktoré sa potom použijú na konfiguráciu Dátový zdroj fazuľa:

@Autowired private Environment environment; @Bean public DataSource dataSource () {JdbcDataSource dataSource = nový JdbcDataSource (); dataSource.setUrl (environment.getRequiredProperty ("db.url")); dataSource.setUser (environment.getRequiredProperty ("db.username")); dataSource.setPassword (environment.getRequiredProperty ("db.password"));
 vrátiť dátový zdroj; }

Teraz definujeme niekoľko fazúľ na prácu s operáciami prístupu do databázy:

@Bean public TransactionAwareDataSourceProxy transactionAwareDataSource () {vrátiť nový TransactionAwareDataSourceProxy (dataSource ()); } @Bean public DataSourceTransactionManager transactionManager () {vrátiť nový DataSourceTransactionManager (dataSource ()); } @Bean public DataSourceConnectionProvider connectionProvider () {vrátiť nový DataSourceConnectionProvider (transactionAwareDataSource ()); } @Bean public ExceptionTranslator exceptionTransformer () {vrátiť nový ExceptionTranslator (); } @Bean public DefaultDSLContext dsl () {vrátiť nový DefaultDSLContext (configuration ()); }

Na záver poskytujeme Jooq Konfigurácia implementáciu a vyhlásiť ju za jarnú fazuľu, ktorú má používať DSLContext trieda:

@Bean public DefaultConfiguration configuration () {DefaultConfiguration JooqConfiguration = nový DefaultConfiguration (); jooqConfiguration.set (connectionProvider ()); jooqConfiguration.set (nový DefaultExecuteListenerProvider (exceptionTransformer ())); Reťazec sqlDialectName = environment.getRequiredProperty ("jooq.sql.dialect"); SQLDialect dialect = SQLDialect.valueOf (sqlDialectName); jooqConfiguration.set (dialekt); návrat jooqConfiguration; }

5. Používanie jOOQ s jarou

Táto časť demonštruje použitie Jooq v bežných dotazoch na prístup k databáze. Existujú dva testy, jeden na potvrdenie a druhý na vrátenie späť, pre každý typ operácie „zápisu“, vrátane vkladania, aktualizácie a mazania údajov. Použitie operácie „čítanie“ je ilustrované pri výbere údajov na overenie otázok „zápisu“.

Začneme vyhlásením za káblové pripojenie DSLContext objekt a inštancie tried generovaných Jooq, ktoré majú používať všetky testovacie metódy:

@Autowired private DSLContext dsl; Autor autor = Autor.AUTHOR; Book book = Book.BOOK; AuthorBook authorBook = AuthorBook.AUTHOR_BOOK;

5.1. Vkladanie údajov

Prvým krokom je vloženie údajov do tabuliek:

dsl.insertInto (autor) .set (autor.ID, 4) .set (autor.FIRST_NAME, "Herbert") .set (autor.LAST_NAME, "Schildt") .execute (); dsl.insertInto (kniha) .set (book.ID, 4) .set (book.TITLE, "Sprievodca pre začiatočníkov") .execute (); dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 4) .execute ();

A VYBERTE dopyt na extrakciu údajov:

Výsledok result = dsl .select (author.ID, author.LAST_NAME, DSL.count ()) .from (author) .join (authorBook) .on (author.ID.equal (authorBook.AUTHOR_ID)) .join (kniha). on (authorBook.BOOK_ID.equal (book.ID)) .groupBy (author.LAST_NAME) .fetch ();

Vyššie uvedený dotaz produkuje nasledujúci výstup:

+ ---- + --------- + ----- + | ID | LAST_NAME | počet | + ---- + --------- + ----- + | 1 | Sierra | 2 | | 2 | Bates | 1 | | 4 | Schildt | 1 | + ---- + --------- + ----- +

Výsledok potvrdzuje Tvrdiť API:

assertEquals (3, result.size ()); assertEquals ("Sierra", result.getValue (0, autor.LAST_NAME)); assertEquals (Integer.valueOf (2), result.getValue (0, DSL.count ())); assertEquals ("Schildt", result.getValue (2, autor.LAST_NAME)); assertEquals (Integer.valueOf (1), result.getValue (2, DSL.count ()));

Ak dôjde k zlyhaniu z dôvodu neplatného dotazu, vyvolá sa výnimka a transakcia sa vráti späť. V nasledujúcom príklade je VLOŽTE dopyt porušuje obmedzenie cudzieho kľúča, čo vedie k výnimke:

@Test (očakáva sa = DataAccessException.class) public void givenInvalidData_whenInserting_thenFail () {dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 5) .execute (); }

5.2. Aktualizácia údajov

Teraz aktualizujme existujúce údaje:

dsl.update (autor) .set (autor.LAST_NAME, "Baeldung"). kde (autor.ID.equal (3)) .execute (); dsl.update (kniha) .set (kniha.TITLE, "Budovanie rozhrania REST API s jarou") .where (kniha.ID.equal (3)) .execute (); dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 3) .set (authorBook.BOOK_ID, 3) .execute ();

Získajte potrebné údaje:

Výsledok result = dsl .select (author.ID, author.LAST_NAME, book.TITLE) .from (author) .join (authorBook) .on (author.ID.equal (authorBook.AUTHOR_ID)) .join (book) .on ( authorBook.BOOK_ID.equal (book.ID)) .where (author.ID.equal (3)) .fetch ();

Výstup by mal byť:

+ ---- + --------- + ---------------------------------- + | ID | LAST_NAME | TITLE | + ---- + --------- + ---------------------------------- + | 3 | Baeldung | Budovanie vášho REST API s jarou | + ---- + --------- + ---------------------------------- +

Nasledujúci test overí, či Jooq pracoval podľa očakávaní:

assertEquals (1, result.size ()); assertEquals (Integer.valueOf (3), result.getValue (0, autor.ID)); assertEquals ("Baeldung", result.getValue (0, autor.LAST_NAME)); assertEquals ("Budovanie vášho REST API s jarou", result.getValue (0, book.TITLE));

V prípade zlyhania sa vyvolá výnimka a transakcia sa vráti späť, čo potvrdíme testom:

@Test (očakáva sa = DataAccessException.class) public void givenInvalidData_whenUpdating_thenFail () {dsl.update (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 5) .execute (); }

5.3. Mazanie údajov

Nasledujúca metóda odstráni niektoré údaje:

dsl.delete (autor). kde [autor.ID.lt (3)) .execute ();

Tu je dopyt na prečítanie príslušnej tabuľky:

Výsledok result = dsl .select (autor.ID, autor.FIRST_NAME, autor.LAST_NAME) .from (autor) .fetch ();

Výstup dotazu:

+ ---- + ---------- + --------- + | ID | FIRST_NAME | LAST_NAME | + ---- + ---------- + --------- + | 3 | Bryan | Basham | + ---- + ---------- + --------- +

Nasledujúci test overuje vymazanie:

assertEquals (1, result.size ()); assertEquals ("Bryan", result.getValue (0, autor.FIRST_NAME)); assertEquals ("Basham", result.getValue (0, autor.LAST_NAME));

Na druhej strane, ak je dotaz neplatný, vyvolá výnimku a transakcia sa vráti späť. Nasledujúci test preukáže, že:

@Test (očakáva sa = DataAccessException.class) public void givenInvalidData_whenDeleting_thenFail () {dsl.delete (kniha). Kde (kniha.ID.equal (1)) .execute (); }

6. Záver

Tento výukový program predstavil základy Jooq, knižnice Java pre prácu s databázami. Zahŕňalo kroky na generovanie zdrojového kódu zo štruktúry databázy a spôsob interakcie s touto databázou pomocou novo vytvorených tried.

Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub.


$config[zx-auto] not found$config[zx-overlay] not found