Bevezetés a Jooq-ba tavasszal

1. Áttekintés

Ez a cikk bemutatja a Jooq objektumorientált lekérdezést (Jooq), valamint annak egyszerű beállítását a tavaszi keretrendszerrel együttműködve.

A legtöbb Java-alkalmazás rendelkezik valamilyen SQL-perzisztenciával, és magasabb szintű eszközök, például a JPA segítségével érheti el ezt a réteget. És bár ez hasznos, egyes esetekben valóban szükség van egy finomabb, árnyaltabb eszközre az adatok eléréséhez, vagy ahhoz, hogy valóban kihasználhassa mindazt, amit a mögöttes DB kínál.

A Jooq elkerüli néhány tipikus ORM-mintát, és olyan kódot generál, amely lehetővé teszi számunkra, hogy tipusbiztonsági lekérdezéseket készítsünk, és tiszta és hatékony, folyékony API-n keresztül teljes ellenőrzést kapjunk a létrehozott SQL felett.

Ez a cikk a Spring MVC-re összpontosít. A tavaszi indítás támogatása a jOOQ cikkünkben leírjuk, hogyan lehet a jOOQ-ot használni a tavaszi indításban.

2. Maven-függőségek

A következő függőségek szükségesek a kód futtatásához ebben az oktatóanyagban.

2.1. jOOQ

 org.jooq jooq 3.2.14 

2.2. Tavaszi

Számos tavaszi függőség szükséges a példánkhoz; a dolgok egyszerűsítéséhez azonban csak kettőt kell kifejezetten felvenni a POM fájlba:

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

2.3. Adatbázis

A dolgunk megkönnyítése érdekében felhasználjuk a H2 beágyazott adatbázist:

 com.h2adatbázis h2 1.4.191 

3. Kódgenerálás

3.1. Adatbázis felépítése

Bemutatjuk az adatbázis szerkezetét, amellyel a cikkben dolgozunk. Tegyük fel, hogy létre kell hoznunk egy adatbázist egy kiadó számára az általuk kezelt könyvek és szerzők információinak tárolására, ahol egy szerző sok könyvet írhat, és egy könyvet sok szerző társszerzőként írhat.

Az egyszerűség érdekében csak három táblázatot fogunk létrehozni: a könyv könyvekhez, szerző a szerzők számára, és egy másik táblázat hívott szerző_könyv hogy képviseljék a szerzők és a könyvek közötti sok-sok kapcsolatot. A szerző táblázat három oszloppal rendelkezik: id, keresztnév, és vezetéknév. A könyv táblázat csak a cím oszlop és a id elsődleges kulcs.

A következő SQL lekérdezések, amelyek a intro_schema.sql erőforrásfájl, a már korábban beállított adatbázissal kerül végrehajtásra a szükséges táblák létrehozásához és minta adatokkal való feltöltéséhez:

TÖRLŐ TÁBLÁZAT, HA LÉTEZIK szerző_könyv, szerző, könyv; CREATE TABLE szerző (id INT NULL PRIMARY KEY, first_name VARCHAR (50), last_name VARCHAR (50) NOT NULL); CREATE TABLE book (id INT NULL PRIMARY KEY, cím VARCHAR (100) NOT NULL); CREATE TABLE author_book (author_id INT NULL, book_id INT NOT NULL, PRIMARY KEY (author_id, book_id), CONSTRAINT fk_ab_author FOREIGN KEY (author_id) REFERENCES szerző (id) UPDATE CASCADE ON DELETE CASCADE__ CONSTRAINT (id)); INSERT INTO author 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 programozó'); INSERT INTO author_book ÉRTÉKEK (1, 1), (1, 3), (2, 1);

3.2. Tulajdonságok Maven Plugin

Három különböző Maven bővítményt fogunk használni a Jooq kód előállításához. Ezek közül az első a Properties Maven plugin.

Ez a bővítmény a konfigurációs adatok kiolvasására szolgál egy erőforrás fájlból. Nem szükséges, mivel az adatok közvetlenül hozzáadhatók a POM-hoz, de célszerű a tulajdonságokat kívülről kezelni.

Ebben a szakaszban meghatározzuk az adatbázis-kapcsolatok tulajdonságait, beleértve a JDBC illesztőprogram osztályát, az adatbázis URL-jét, a felhasználónevét és a jelszavát egy megnevezett fájlban. intro_config.properties. Ezen tulajdonságok külsővé tétele megkönnyíti az adatbázis váltását, vagy csak a konfigurációs adatok módosítását.

A read-project-properties Ennek a bővítménynek a célját egy korai szakaszhoz kell kötni, hogy a konfigurációs adatokat fel lehessen készíteni más pluginok használatára. Ebben az esetben a inicializálni fázis:

 org.codehaus.mojo properties-maven-plugin 1.0.0 inicializálja a read-project-tulajdonságokat src / main / resources / intro_config.properties 

3.3. SQL Maven beépülő modul

Az SQL Maven beépülő modult SQL utasítások végrehajtására használják adatbázis táblák létrehozására és feltöltésére. Kihasználja azokat a tulajdonságokat, amelyeket a intro_config.properties fájlt a Properties Maven plugin segítségével, és vegye ki az SQL utasításokat a intro_schema.sql forrás.

Az SQL Maven beépülő modul az alábbiak szerint van konfigurálva:

 org.codehaus.mojo sql-maven-plugin 1.5 inicializálás végrehajtása $ {db.driver} $ {db.url} $ {db.username} $ {db.password} src / main / resources / intro_schema.sql com.h2adatbázis h2 1.4.191 

Ne feledje, hogy ezt a bővítményt később kell elhelyezni, mint a Properties Maven beépülő modult a POM fájlban, mivel végrehajtási céljaik ugyanahhoz a fázishoz vannak kötve, és a Maven a felsorolt ​​sorrendben hajtja végre őket.

3.4. jOOQ Codegen beépülő modul

A Jooq Codegen beépülő modul Java-kódot generál egy adatbázis-tábla felépítéséből. Az generál célt kell kötni a generál-források szakasz a végrehajtás helyes sorrendjének biztosítása érdekében. A plugin metaadatai a következőképpen néznek ki:

 org.jooq jooq-codegen-maven $ {org.jooq.version} generációs források $ {db.driver} $ {db.url} $ {db.username} $ {db.password} com.baeldung.jooq. bevezetés.db src / main / java 

3.5. Kód létrehozása

A forráskód-előállítás befejezéséhez futtatnunk kell a Maven-t generál-források fázis. Az Eclipse programban ezt úgy tehetjük meg, hogy jobb gombbal kattintunk a projektre, és kiválasztjuk Run As –>Maven generációs források. A parancs végrehajtása után a szerző, könyv, szerző_könyv táblák (és még sok más az osztályok támogatására) generálódnak.

Tanuljunk táblázatosztályokba, hogy lássuk, mit készített a Jooq. Minden osztálynak van egy statikus mezője, ugyanazzal a névvel, mint az osztály, azzal a különbséggel, hogy a névben minden betű nagybetűvel szerepel. A következők a kódrészletek, amelyek a létrehozott osztályok definícióiból származnak:

A Szerző osztály:

public class Author kiterjeszti a TableImpl {public static final Szerző AUTHOR = új Szerző (); // az osztály többi tagja}

A Könyv osztály:

public class Book kiterjeszti a TableImpl {public static final Book BOOK = új könyv (); // az osztály többi tagja}

A AuthorBook osztály:

public class AuthorBook kiterjeszti a TableImpl {public static final AuthorBook AUTHOR_BOOK = new AuthorBook (); // az osztály többi tagja}

Az ilyen statikus mezők által hivatkozott példányok adatelérési objektumokként szolgálnak a megfelelő táblák ábrázolására, ha a projekt más rétegeivel dolgoznak.

4. Tavaszi konfiguráció

4.1. A jOOQ Kivételek fordítása tavaszra

Annak érdekében, hogy a Jooq végrehajtásából származó kivételek összhangban legyenek az adatbázis-hozzáférés Spring támogatásával, le kell fordítanunk őket a DataAccessException osztály.

Határozzuk meg a ExecuteListener interfész a kivételek konvertálásához:

public class ExceptionTranslator kiterjeszti a DefaultExecuteListener {public void kivétel (ExecuteContext context) {SQLDialect dialect = context.configuration (). dialect (); SQLExceptionTranslator translator = új SQLErrorCodeSQLExceptionTranslator (dialect.name ()); context.exception (translator .translate ("Hozzáférési adatbázis a Jooq használatával", context.sql (), context.sqlException ())); }}

Ezt az osztályt a tavaszi alkalmazás kontextus fogja használni.

4.2. A tavasz konfigurálása

Ebben a szakaszban végigvezetik a PersistenceContext amely metaadatokat és babot tartalmaz a tavaszi alkalmazás kontextusában.

Kezdjük azzal, hogy a szükséges kommentárokat alkalmazzuk az osztályhoz:

  • @ Konfiguráció: Tegye az osztályt babkonténerként való felismerésre
  • @ComponentScan: Beolvasási irányelvek konfigurálása, beleértve a érték opció a csomagok tömbjének deklarálásához az összetevők kereséséhez. Ebben az oktatóanyagban a keresendő csomag a Jooq Codegen Maven plugin által generált csomag
  • @EnableTransactionManagement: A tranzakciók tavaszi kezelésének engedélyezése
  • @PropertySource: Jelölje meg a betöltendő tulajdonságfájlok helyét. A cikk értéke a konfigurációs adatokat és az adatbázis dialektusát tartalmazó fájlra mutat, amely véletlenül ugyanaz a fájl, amelyet a 4.1.
@Configuration @ComponentScan ({"com.baeldung.Jooq.introduction.db.public_.tables"}) @EnableTransactionManagement @PropertySource ("classpath: intro_config.properties") public class PersistenceContext {// Egyéb nyilatkozatok}

Ezután használjon egy Környezet objektumot a konfigurációs adatok megszerzéséhez, amelyeket azután a Adatforrás bab:

@Autowired magánkörnyezet; @Bean public DataSource dataSource () {JdbcDataSource dataSource = új JdbcDataSource (); dataSource.setUrl (environment.getRequiredProperty ("db.url")); dataSource.setUser (environment.getRequiredProperty ("db.felhasználónév")); dataSource.setPassword (környezet.getRequiredProperty ("db.jelszó"));
 return dataSource; }

Most több babot definiálunk az adatbázis-hozzáférési műveletekhez:

@Bean public TransactionAwareDataSourceProxyactionAwareDataSource () {return new TransactionAwareDataSourceProxy (dataSource ()); } @Bean public DataSourceTransactionManageractionManager () {return new DataSourceTransactionManager (dataSource ()); } @Bean public DataSourceConnectionProvider connectionProvider () {return new DataSourceConnectionProvider (actionAwareDataSource ()); } @Bean public ExceptionTranslator kivételTransformer () {return new ExceptionTranslator (); } @Bean public DefaultDSLContext dsl () {return new DefaultDSLContext (configuration ()); }

Végül biztosítunk egy Jooq-ot Konfiguráció végrehajtását, és nyilvánítsa azt tavaszi babként, amelyet a DSLContext osztály:

@Bean public DefaultConfiguration konfiguráció () {DefaultConfiguration JooqConfiguration = új DefaultConfiguration (); jooqConfiguration.set (connectionProvider ()); jooqConfiguration.set (új DefaultExecuteListenerProvider (kivételTransformer ())); Karakterlánc sqlDialectName = environment.getRequiredProperty ("jooq.sql.dialect"); SQLDialect dialektus = SQLDialect.valueOf (sqlDialectName); jooqConfiguration.set (nyelvjárás); return jooqConfiguration; }

5. A jOOQ használata tavasszal

Ez a szakasz bemutatja a Jooq használatát a közös adatbázis-hozzáférési lekérdezésekben. Két teszt van, egy a véglegesítésre és egy a visszagörgetésre, minden típusú „írási” művelethez, beleértve az adatok beszúrását, frissítését és törlését. Az „olvasás” művelet használatát szemlélteti az adatok kiválasztása az „írási” lekérdezések ellenőrzéséhez.

Kezdjük azzal, hogy deklaráljuk az automatikus vezetéket DSLContext objektum és a Jooq által generált osztályok példányai, amelyeket az összes tesztelési módszer használni fog:

@Autowired private DSLContext dsl; Szerző szerző = Szerző.AUTHOR; Könyvkönyv = Könyv.BOOK; AuthorBook authorBook = AuthorBook.AUTHOR_BOOK;

5.1. Adatok beszúrása

Az első lépés az adatok beszúrása a táblázatokba:

dsl.insertInto (author) .set (author.ID, 4) .set (author.FIRST_NAME, "Herbert") .set (author.LAST_NAME, "Schildt") .execute (); dsl.insertInto (book) .set (book.ID, 4) .set (book.TITLE, "Kezdő útmutató") .execute (); dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 4) .execute ();

A SELECT lekérdezés az adatok kinyerésére:

Eredmény eredmény = dsl .select (szerző.ID, szerző.LAST_NAME, DSL.szám ()). -től (szerző) .csatlakozzon (szerzőkönyv) .on (szerző.ID.egyenlő (szerzőkönyv.AUTHOR_ID)) .csatlakozzon (könyv). on (authorBook.BOOK_ID.equal (book.ID)) .groupBy (author.LAST_NAME) .fetch ();

A fenti lekérdezés a következő kimenetet hozza létre:

+ ---- + --------- + ----- + | ID | LAST_NAME | számlálás | + ---- + --------- + ----- + | 1 | Sierra | 2 | | 2 | Bates | 1 | | 4 | Schildt | 1 | + ---- + --------- + ----- +

Az eredményt a Állítsd API:

assertEquals (3, eredmény.méret ()); assertEquals ("Sierra", result.getValue (0, szerző.LAST_NAME)); assertEquals (Integer.valueOf (2), result.getValue (0, DSL.count ())); assertEquals ("Schildt", result.getValue (2, szerző.LAST_NAME)); assertEquals (Integer.valueOf (1), result.getValue (2, DSL.count ()));

Ha érvénytelen lekérdezés miatt hiba lép fel, kivételt dob, és a tranzakció visszaáll. A következő példában a INSERT a lekérdezés megsérti az idegen kulcs korlátozását, és kivételt eredményez:

@Test (várható = DataAccessException.class) public void givenInvalidData_whenInserting_thenFail () {dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 5) .execute (); }

5.2. Adatok frissítése

Most frissítsük a meglévő adatokat:

dsl.update (author) .set (author.LAST_NAME, "Baeldung") .where (author.ID.equal (3)) .execute (); dsl.update (book) .set (book.TITLE, "A REST API felépítése tavasszal") .where (book.ID.equal (3)) .execute (); dsl.insertInto (authorBook) .set (authorBook.AUTHOR_ID, 3) .set (authorBook.BOOK_ID, 3) .execute ();

Szerezze be a szükséges adatokat:

Eredmény eredmény = 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)) .hol (author.ID.equal (3)) .fetch ();

A kimenetnek a következőknek kell lennie:

+ ---- + --------- + ---------------------------------- + | ID | LAST_NAME | TITLE | + ---- + --------- + ---------------------------------- + | 3 | Baeldung | A REST API felépítése tavasszal | + ---- + --------- + ---------------------------------- +

A következő teszt ellenőrzi, hogy a Jooq a várt módon működött-e:

assertEquals (1, eredmény.méret ()); assertEquals (Integer.valueOf (3), result.getValue (0, szerző.ID)); assertEquals ("Baeldung", result.getValue (0, szerző.LAST_NAME)); assertEquals ("A REST API felépítése tavasszal", result.getValue (0, book.TITLE));

Meghibásodás esetén kivételt dobunk, és a tranzakció visszagördül, amit egy teszttel megerősítünk:

@Test (várható = DataAccessException.class) public void givenInvalidData_whenUpdating_thenFail () {dsl.update (authorBook) .set (authorBook.AUTHOR_ID, 4) .set (authorBook.BOOK_ID, 5) .execute (); }

5.3. Adatok törlése

A következő módszer töröl néhány adatot:

dsl.delete (author) .where (author.ID.lt (3)) .execute ();

Itt van a lekérdezés az érintett táblázat elolvasására:

Eredmény eredmény = dsl .select (szerző.ID, szerző.FIRST_NAME, szerző.LAST_NAME). -től (szerző) .fetch ();

A lekérdezés kimenete:

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

A következő teszt ellenőrzi a törlést:

assertEquals (1, eredmény.méret ()); assertEquals ("Bryan", result.getValue (0, szerző.FIRST_NAME)); assertEquals ("Basham", result.getValue (0, szerző.LAST_NAME));

Másrészt, ha egy lekérdezés érvénytelen, kivételt dob, és a tranzakció visszaáll. A következő teszt igazolja, hogy:

@Test (várható = DataAccessException.class) public void givenInvalidData_whenDeleting_thenFail () {dsl.delete (book) .where (book.ID.equal (1)) .execute (); }

6. Következtetés

Ez az oktatóanyag bemutatja a Jooq, az adatbázisokkal való munka Java könyvtárának alapjait. Kitért a forráskód adatbázis-struktúrából történő generálásának lépéseire és arra, hogy miként lehet az adatbázissal kölcsönhatásba lépni az újonnan létrehozott osztályok segítségével.

Ezen példák és kódrészletek megvalósítása megtalálható egy GitHub projektben.


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