diff --git a/persistence-modules/jooq/pom.xml b/persistence-modules/jooq/pom.xml
new file mode 100644
index 0000000000..f0c5a27a96
--- /dev/null
+++ b/persistence-modules/jooq/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+ jooq
+ 0.0.1-SNAPSHOT
+ jooq-examples
+ jar
+ jOOQ Examples
+
+
+ com.baeldung
+ persistence-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.jooq
+ jooq
+ 3.13.4
+
+
+ org.jooq
+ jooq-meta
+ 3.13.4
+
+
+ org.jooq
+ jooq-codegen
+ 3.13.4
+
+
+ org.postgresql
+ postgresql
+ 42.2.16
+
+
+ com.h2database
+ h2
+ 1.4.200
+
+
+
+
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java
new file mode 100644
index 0000000000..0427b71c25
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java
@@ -0,0 +1,57 @@
+package com.baeldung.jooq;
+
+import org.jooq.Condition;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.Result;
+import org.jooq.SelectFieldOrAsterisk;
+import org.jooq.Table;
+import org.jooq.UpdatableRecord;
+
+import java.util.Map;
+
+public class Crud {
+
+ public static > void save(UpdatableRecord record) {
+ record.store();
+ }
+
+ public static Result getAll(DSLContext context, Table extends Record> table) {
+ return context.select()
+ .from(table)
+ .fetch();
+ }
+
+ public static Result getFields(DSLContext context, Table extends Record> table, SelectFieldOrAsterisk... fields) {
+ return context.select(fields)
+ .from(table)
+ .fetch();
+ }
+
+ public static R getOne(DSLContext context, Table table, Condition condition) {
+ return context.fetchOne(table, condition);
+ }
+
+ public static void update(DSLContext context, Table extends Record> table, Map, T> values, Condition condition) {
+ context.update(table)
+ .set(values)
+ .where(condition)
+ .execute();
+ }
+
+ public static > void update(UpdatableRecord record) {
+ record.update();
+ }
+
+ public static void delete(DSLContext context, Table extends Record> table, Condition condition) {
+ context.delete(table)
+ .where(condition)
+ .execute();
+ }
+
+ public static > void delete(UpdatableRecord record) {
+ record.delete();
+ }
+
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java
new file mode 100644
index 0000000000..87a7b6439e
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java
@@ -0,0 +1,117 @@
+package com.baeldung.jooq;
+
+import com.baeldung.jooq.model.tables.Article;
+import com.baeldung.jooq.model.tables.Author;
+import com.baeldung.jooq.model.tables.records.ArticleRecord;
+import com.baeldung.jooq.model.tables.records.AuthorRecord;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.Result;
+import org.jooq.SQLDialect;
+import org.jooq.impl.DSL;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+import static com.baeldung.jooq.Crud.delete;
+import static com.baeldung.jooq.Crud.getAll;
+import static com.baeldung.jooq.Crud.getFields;
+import static com.baeldung.jooq.Crud.getOne;
+import static com.baeldung.jooq.Crud.save;
+import static com.baeldung.jooq.Crud.update;
+
+public class CrudExamples {
+
+ public void crudExamples() throws SQLException {
+ String userName = "username";
+ String password = "password";
+ String url = "jdbc:postgresql://db_url:5432/baeldung_database";
+
+ Connection conn = DriverManager.getConnection(url, userName, password);
+ DSLContext context = DSL.using(conn, SQLDialect.POSTGRES);
+
+ createValues(context);
+ readValues(context);
+ updateValues(context);
+ deleteValues(context);
+ }
+
+ private void createValues(DSLContext context) {
+ ArticleRecord article = context.newRecord(Article.ARTICLE);
+
+ article.setId(2);
+ article.setTitle("jOOQ examples");
+ article.setDescription("A few examples of jOOQ CRUD operations");
+ article.setAuthorId(1);
+
+ save(article);
+
+ AuthorRecord author = context.newRecord(Author.AUTHOR);
+ author.setId(1);
+ author.setFirstName("John");
+ author.setLastName("Smith");
+ author.setAge(40);
+
+ save(author);
+ }
+
+ private void readValues(DSLContext context) {
+ Result authors = getAll(
+ context,
+ Author.AUTHOR
+ );
+
+ 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);
+ });
+
+ Result articles = getFields(
+ context,
+ Author.AUTHOR,
+ Article.ARTICLE.ID, Article.ARTICLE.TITLE
+ );
+
+ AuthorRecord author = getOne(
+ context,
+ Author.AUTHOR,
+ Author.AUTHOR.ID.eq(1)
+ );
+ }
+
+ private void updateValues(DSLContext context) {
+ HashMap, String> fieldsToUpdate = new HashMap<>();
+ fieldsToUpdate.put(Author.AUTHOR.FIRST_NAME, "David");
+ fieldsToUpdate.put(Author.AUTHOR.LAST_NAME, "Brown");
+ update(
+ context,
+ Author.AUTHOR,
+ fieldsToUpdate,
+ Author.AUTHOR.ID.eq(1)
+ );
+
+ ArticleRecord article = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1));
+ article.setTitle("A New Article Title");
+ update(
+ article
+ );
+ }
+
+ private void deleteValues(DSLContext context) {
+ delete(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+
+ AuthorRecord author = context.fetchOne(Author.AUTHOR, Author.AUTHOR.ID.eq(1));
+ delete(author);
+ }
+
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/DefaultCatalog.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/DefaultCatalog.java
new file mode 100644
index 0000000000..b18484877a
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/DefaultCatalog.java
@@ -0,0 +1,44 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model;
+
+
+import org.jooq.Schema;
+import org.jooq.impl.CatalogImpl;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class DefaultCatalog extends CatalogImpl {
+
+ private static final long serialVersionUID = 1035293962;
+
+ /**
+ * The reference instance of DEFAULT_CATALOG
+ */
+ public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog();
+
+ /**
+ * The schema public.
+ */
+ public final Public PUBLIC = Public.PUBLIC;
+
+ /**
+ * No further instances allowed
+ */
+ private DefaultCatalog() {
+ super("");
+ }
+
+ @Override
+ public final List getSchemas() {
+ return Arrays.asList(
+ Public.PUBLIC);
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Keys.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Keys.java
new file mode 100644
index 0000000000..461ffb58c7
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Keys.java
@@ -0,0 +1,48 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model;
+
+
+import com.baeldung.jooq.model.tables.Article;
+import com.baeldung.jooq.model.tables.Author;
+import com.baeldung.jooq.model.tables.records.ArticleRecord;
+import com.baeldung.jooq.model.tables.records.AuthorRecord;
+import org.jooq.ForeignKey;
+import org.jooq.TableField;
+import org.jooq.UniqueKey;
+import org.jooq.impl.Internal;
+
+
+/**
+ * A class modelling foreign key relationships and constraints of tables of
+ * the public schema.
+ */
+@SuppressWarnings({"all", "unchecked", "rawtypes"})
+public class Keys {
+
+ // -------------------------------------------------------------------------
+ // UNIQUE and PRIMARY KEY definitions
+ // -------------------------------------------------------------------------
+
+ public static final UniqueKey ARTICLE_PKEY = UniqueKeys0.ARTICLE_PKEY;
+ public static final UniqueKey AUTHOR_PKEY = UniqueKeys0.AUTHOR_PKEY;
+
+ // -------------------------------------------------------------------------
+ // FOREIGN KEY definitions
+ // -------------------------------------------------------------------------
+ public static final ForeignKey ARTICLE__XXX = ForeignKeys0.ARTICLE__XXX;
+
+ // -------------------------------------------------------------------------
+ // [#1459] distribute members to avoid static initialisers > 64kb
+ // -------------------------------------------------------------------------
+
+ private static class UniqueKeys0 {
+ public static final UniqueKey ARTICLE_PKEY = Internal.createUniqueKey(Article.ARTICLE, "article_pkey", new TableField[]{Article.ARTICLE.ID}, true);
+ public static final UniqueKey AUTHOR_PKEY = Internal.createUniqueKey(Author.AUTHOR, "author_pkey", new TableField[]{Author.AUTHOR.ID}, true);
+ }
+
+ private static class ForeignKeys0 {
+ public static final ForeignKey ARTICLE__XXX = Internal.createForeignKey(Keys.AUTHOR_PKEY, Article.ARTICLE, "xxx", new TableField[]{Article.ARTICLE.AUTHOR_ID}, true);
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Public.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Public.java
new file mode 100644
index 0000000000..02c664522b
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Public.java
@@ -0,0 +1,59 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model;
+
+import com.baeldung.jooq.model.tables.Article;
+import com.baeldung.jooq.model.tables.Author;
+import org.jooq.Catalog;
+import org.jooq.Table;
+import org.jooq.impl.SchemaImpl;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({"all", "unchecked", "rawtypes"})
+public class Public extends SchemaImpl {
+
+ private static final long serialVersionUID = -2049410122;
+
+ /**
+ * The reference instance of public
+ */
+ public static final Public PUBLIC = new Public();
+
+ /**
+ * The table public.article.
+ */
+ public final Article ARTICLE = Article.ARTICLE;
+
+ /**
+ * The table public.author.
+ */
+ public final Author AUTHOR = Author.AUTHOR;
+
+ /**
+ * No further instances allowed
+ */
+ private Public() {
+ super("public", null);
+ }
+
+
+ @Override
+ public Catalog getCatalog() {
+ return DefaultCatalog.DEFAULT_CATALOG;
+ }
+
+ @Override
+ public final List> getTables() {
+ return Arrays.>asList(
+ Article.ARTICLE,
+ Author.AUTHOR
+ );
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Tables.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Tables.java
new file mode 100644
index 0000000000..eb1f14e05a
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/Tables.java
@@ -0,0 +1,25 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model;
+
+import com.baeldung.jooq.model.tables.Article;
+import com.baeldung.jooq.model.tables.Author;
+
+/**
+ * Convenience access to all tables in public
+ */
+@SuppressWarnings({"all", "unchecked", "rawtypes"})
+public class Tables {
+
+ /**
+ * The table public.article.
+ */
+ public static final Article ARTICLE = Article.ARTICLE;
+
+ /**
+ * The table public.author.
+ */
+ public static final Author AUTHOR = Author.AUTHOR;
+
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Article.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Article.java
new file mode 100644
index 0000000000..3159c91aa8
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Article.java
@@ -0,0 +1,159 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model.tables;
+
+
+import com.baeldung.jooq.model.Keys;
+import com.baeldung.jooq.model.Public;
+import com.baeldung.jooq.model.tables.records.ArticleRecord;
+import org.jooq.Field;
+import org.jooq.ForeignKey;
+import org.jooq.Name;
+import org.jooq.Record;
+import org.jooq.Row4;
+import org.jooq.Schema;
+import org.jooq.Table;
+import org.jooq.TableField;
+import org.jooq.TableOptions;
+import org.jooq.UniqueKey;
+import org.jooq.impl.DSL;
+import org.jooq.impl.TableImpl;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class Article extends TableImpl {
+
+ private static final long serialVersionUID = -1401275800;
+
+ /**
+ * The reference instance of public.article
+ */
+ public static final Article ARTICLE = new Article();
+
+ /**
+ * The class holding records for this type
+ */
+ @Override
+ public Class getRecordType() {
+ return ArticleRecord.class;
+ }
+
+ /**
+ * The column public.article.id.
+ */
+ public final TableField ID = createField(DSL.name("id"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
+
+ /**
+ * The column public.article.title.
+ */
+ public final TableField TITLE = createField(DSL.name("title"), org.jooq.impl.SQLDataType.VARCHAR(255).nullable(false), this, "");
+
+ /**
+ * The column public.article.description.
+ */
+ public final TableField DESCRIPTION = createField(DSL.name("description"), org.jooq.impl.SQLDataType.VARCHAR(255), this, "");
+
+ /**
+ * The column public.article.author_id.
+ */
+ public final TableField AUTHOR_ID = createField(DSL.name("author_id"), org.jooq.impl.SQLDataType.INTEGER, this, "");
+
+ /**
+ * Create a public.article table reference
+ */
+ public Article() {
+ this(DSL.name("article"), null);
+ }
+
+ /**
+ * Create an aliased public.article table reference
+ */
+ public Article(String alias) {
+ this(DSL.name(alias), ARTICLE);
+ }
+
+ /**
+ * Create an aliased public.article table reference
+ */
+ public Article(Name alias) {
+ this(alias, ARTICLE);
+ }
+
+ private Article(Name alias, Table aliased) {
+ this(alias, aliased, null);
+ }
+
+ private Article(Name alias, Table aliased, Field>[] parameters) {
+ super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table());
+ }
+
+ public Article(Table child, ForeignKey key) {
+ super(child, key, ARTICLE);
+ }
+
+ @Override
+ public Schema getSchema() {
+ return Public.PUBLIC;
+ }
+
+ @Override
+ public UniqueKey getPrimaryKey() {
+ return Keys.ARTICLE_PKEY;
+ }
+
+ @Override
+ public List> getKeys() {
+ return Arrays.>asList(Keys.ARTICLE_PKEY);
+ }
+
+ @Override
+ public List> getReferences() {
+ return Arrays.>asList(Keys.ARTICLE__XXX);
+ }
+
+ public Author author() {
+ return new Author(this, Keys.ARTICLE__XXX);
+ }
+
+ @Override
+ public Article as(String alias) {
+ return new Article(DSL.name(alias), this);
+ }
+
+ @Override
+ public Article as(Name alias) {
+ return new Article(alias, this);
+ }
+
+ /**
+ * Rename this table
+ */
+ @Override
+ public Article rename(String name) {
+ return new Article(DSL.name(name), null);
+ }
+
+ /**
+ * Rename this table
+ */
+ @Override
+ public Article rename(Name name) {
+ return new Article(name, null);
+ }
+
+ // -------------------------------------------------------------------------
+ // Row4 type methods
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Row4 fieldsRow() {
+ return (Row4) super.fieldsRow();
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Author.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Author.java
new file mode 100644
index 0000000000..9da9415109
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/Author.java
@@ -0,0 +1,149 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model.tables;
+
+import com.baeldung.jooq.model.Keys;
+import com.baeldung.jooq.model.Public;
+import com.baeldung.jooq.model.tables.records.AuthorRecord;
+import org.jooq.Field;
+import org.jooq.ForeignKey;
+import org.jooq.Name;
+import org.jooq.Record;
+import org.jooq.Row4;
+import org.jooq.Schema;
+import org.jooq.Table;
+import org.jooq.TableField;
+import org.jooq.TableOptions;
+import org.jooq.UniqueKey;
+import org.jooq.impl.DSL;
+import org.jooq.impl.TableImpl;
+
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class Author extends TableImpl {
+
+ private static final long serialVersionUID = -798376522;
+
+ /**
+ * The reference instance of public.author
+ */
+ public static final Author AUTHOR = new Author();
+
+ /**
+ * The class holding records for this type
+ */
+ @Override
+ public Class getRecordType() {
+ return AuthorRecord.class;
+ }
+
+ /**
+ * The column public.author.id.
+ */
+ public final TableField ID = createField(DSL.name("id"), org.jooq.impl.SQLDataType.INTEGER.nullable(false), AUTHOR, "");
+
+ /**
+ * The column public.author.first_name.
+ */
+ public final TableField FIRST_NAME = createField(DSL.name("first_name"), org.jooq.impl.SQLDataType.VARCHAR(255), this, "");
+
+ /**
+ * The column public.author.last_name.
+ */
+ public final TableField LAST_NAME = createField(DSL.name("last_name"), org.jooq.impl.SQLDataType.VARCHAR(255), this, "");
+
+ /**
+ * The column public.author.age.
+ */
+ public final TableField AGE = createField(DSL.name("age"), org.jooq.impl.SQLDataType.INTEGER, this, "");
+
+ /**
+ * Create a public.author table reference
+ */
+ public Author() {
+ this(DSL.name("author"), null);
+ }
+
+ /**
+ * Create an aliased public.author table reference
+ */
+ public Author(String alias) {
+ this(DSL.name(alias), AUTHOR);
+ }
+
+ /**
+ * Create an aliased public.author table reference
+ */
+ public Author(Name alias) {
+ this(alias, AUTHOR);
+ }
+
+ private Author(Name alias, Table aliased) {
+ this(alias, aliased, null);
+ }
+
+ private Author(Name alias, Table aliased, Field>[] parameters) {
+ super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table());
+ }
+
+ public Author(Table child, ForeignKey key) {
+ super(child, key, AUTHOR);
+ }
+
+ @Override
+ public Schema getSchema() {
+ return Public.PUBLIC;
+ }
+
+ @Override
+ public UniqueKey getPrimaryKey() {
+ return Keys.AUTHOR_PKEY;
+ }
+
+ @Override
+ public List> getKeys() {
+ return Arrays.>asList(Keys.AUTHOR_PKEY);
+ }
+
+ @Override
+ public Author as(String alias) {
+ return new Author(DSL.name(alias), this);
+ }
+
+ @Override
+ public Author as(Name alias) {
+ return new Author(alias, this);
+ }
+
+ /**
+ * Rename this table
+ */
+ @Override
+ public Author rename(String name) {
+ return new Author(DSL.name(name), null);
+ }
+
+ /**
+ * Rename this table
+ */
+ @Override
+ public Author rename(Name name) {
+ return new Author(name, null);
+ }
+
+ // -------------------------------------------------------------------------
+ // Row4 type methods
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Row4 fieldsRow() {
+ return (Row4) super.fieldsRow();
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/ArticleRecord.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/ArticleRecord.java
new file mode 100644
index 0000000000..cee17fe716
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/ArticleRecord.java
@@ -0,0 +1,218 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model.tables.records;
+
+
+import com.baeldung.jooq.model.tables.Article;
+
+import org.jooq.Field;
+import org.jooq.Record1;
+import org.jooq.Record4;
+import org.jooq.Row4;
+import org.jooq.impl.UpdatableRecordImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class ArticleRecord extends UpdatableRecordImpl implements Record4 {
+
+ private static final long serialVersionUID = 1297442421;
+
+ /**
+ * Setter for public.article.id.
+ */
+ public void setId(Integer value) {
+ set(0, value);
+ }
+
+ /**
+ * Getter for public.article.id.
+ */
+ public Integer getId() {
+ return (Integer) get(0);
+ }
+
+ /**
+ * Setter for public.article.title.
+ */
+ public void setTitle(String value) {
+ set(1, value);
+ }
+
+ /**
+ * Getter for public.article.title.
+ */
+ public String getTitle() {
+ return (String) get(1);
+ }
+
+ /**
+ * Setter for public.article.description.
+ */
+ public void setDescription(String value) {
+ set(2, value);
+ }
+
+ /**
+ * Getter for public.article.description.
+ */
+ public String getDescription() {
+ return (String) get(2);
+ }
+
+ /**
+ * Setter for public.article.author_id.
+ */
+ public void setAuthorId(Integer value) {
+ set(3, value);
+ }
+
+ /**
+ * Getter for public.article.author_id.
+ */
+ public Integer getAuthorId() {
+ return (Integer) get(3);
+ }
+
+ // -------------------------------------------------------------------------
+ // Primary key information
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Record1 key() {
+ return (Record1) super.key();
+ }
+
+ // -------------------------------------------------------------------------
+ // Record4 type implementation
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Row4 fieldsRow() {
+ return (Row4) super.fieldsRow();
+ }
+
+ @Override
+ public Row4 valuesRow() {
+ return (Row4) super.valuesRow();
+ }
+
+ @Override
+ public Field field1() {
+ return Article.ARTICLE.ID;
+ }
+
+ @Override
+ public Field field2() {
+ return Article.ARTICLE.TITLE;
+ }
+
+ @Override
+ public Field field3() {
+ return Article.ARTICLE.DESCRIPTION;
+ }
+
+ @Override
+ public Field field4() {
+ return Article.ARTICLE.AUTHOR_ID;
+ }
+
+ @Override
+ public Integer component1() {
+ return getId();
+ }
+
+ @Override
+ public String component2() {
+ return getTitle();
+ }
+
+ @Override
+ public String component3() {
+ return getDescription();
+ }
+
+ @Override
+ public Integer component4() {
+ return getAuthorId();
+ }
+
+ @Override
+ public Integer value1() {
+ return getId();
+ }
+
+ @Override
+ public String value2() {
+ return getTitle();
+ }
+
+ @Override
+ public String value3() {
+ return getDescription();
+ }
+
+ @Override
+ public Integer value4() {
+ return getAuthorId();
+ }
+
+ @Override
+ public ArticleRecord value1(Integer value) {
+ setId(value);
+ return this;
+ }
+
+ @Override
+ public ArticleRecord value2(String value) {
+ setTitle(value);
+ return this;
+ }
+
+ @Override
+ public ArticleRecord value3(String value) {
+ setDescription(value);
+ return this;
+ }
+
+ @Override
+ public ArticleRecord value4(Integer value) {
+ setAuthorId(value);
+ return this;
+ }
+
+ @Override
+ public ArticleRecord values(Integer value1, String value2, String value3, Integer value4) {
+ value1(value1);
+ value2(value2);
+ value3(value3);
+ value4(value4);
+ return this;
+ }
+
+ // -------------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------------
+
+ /**
+ * Create a detached ArticleRecord
+ */
+ public ArticleRecord() {
+ super(Article.ARTICLE);
+ }
+
+ /**
+ * Create a detached, initialised ArticleRecord
+ */
+ public ArticleRecord(Integer id, String title, String description, Integer authorId) {
+ super(Article.ARTICLE);
+
+ set(0, id);
+ set(1, title);
+ set(2, description);
+ set(3, authorId);
+ }
+}
diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/AuthorRecord.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/AuthorRecord.java
new file mode 100644
index 0000000000..365de20747
--- /dev/null
+++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/model/tables/records/AuthorRecord.java
@@ -0,0 +1,217 @@
+/*
+ * This file is generated by jOOQ.
+ */
+package com.baeldung.jooq.model.tables.records;
+
+
+import com.baeldung.jooq.model.tables.Author;
+import org.jooq.Field;
+import org.jooq.Record1;
+import org.jooq.Record4;
+import org.jooq.Row4;
+import org.jooq.impl.UpdatableRecordImpl;
+
+
+/**
+ * This class is generated by jOOQ.
+ */
+@SuppressWarnings({ "all", "unchecked", "rawtypes" })
+public class AuthorRecord extends UpdatableRecordImpl implements Record4 {
+
+ private static final long serialVersionUID = -2120822720;
+
+ /**
+ * Setter for public.author.id.
+ */
+ public void setId(Integer value) {
+ set(0, value);
+ }
+
+ /**
+ * Getter for public.author.id.
+ */
+ public Integer getId() {
+ return (Integer) get(0);
+ }
+
+ /**
+ * Setter for public.author.first_name.
+ */
+ public void setFirstName(String value) {
+ set(1, value);
+ }
+
+ /**
+ * Getter for public.author.first_name.
+ */
+ public String getFirstName() {
+ return (String) get(1);
+ }
+
+ /**
+ * Setter for public.author.last_name.
+ */
+ public void setLastName(String value) {
+ set(2, value);
+ }
+
+ /**
+ * Getter for public.author.last_name.
+ */
+ public String getLastName() {
+ return (String) get(2);
+ }
+
+ /**
+ * Setter for public.author.age.
+ */
+ public void setAge(Integer value) {
+ set(3, value);
+ }
+
+ /**
+ * Getter for public.author.age.
+ */
+ public Integer getAge() {
+ return (Integer) get(3);
+ }
+
+ // -------------------------------------------------------------------------
+ // Primary key information
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Record1 key() {
+ return (Record1) super.key();
+ }
+
+ // -------------------------------------------------------------------------
+ // Record4 type implementation
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Row4 fieldsRow() {
+ return (Row4) super.fieldsRow();
+ }
+
+ @Override
+ public Row4 valuesRow() {
+ return (Row4) super.valuesRow();
+ }
+
+ @Override
+ public Field field1() {
+ return Author.AUTHOR.ID;
+ }
+
+ @Override
+ public Field field2() {
+ return Author.AUTHOR.FIRST_NAME;
+ }
+
+ @Override
+ public Field field3() {
+ return Author.AUTHOR.LAST_NAME;
+ }
+
+ @Override
+ public Field field4() {
+ return Author.AUTHOR.AGE;
+ }
+
+ @Override
+ public Integer component1() {
+ return getId();
+ }
+
+ @Override
+ public String component2() {
+ return getFirstName();
+ }
+
+ @Override
+ public String component3() {
+ return getLastName();
+ }
+
+ @Override
+ public Integer component4() {
+ return getAge();
+ }
+
+ @Override
+ public Integer value1() {
+ return getId();
+ }
+
+ @Override
+ public String value2() {
+ return getFirstName();
+ }
+
+ @Override
+ public String value3() {
+ return getLastName();
+ }
+
+ @Override
+ public Integer value4() {
+ return getAge();
+ }
+
+ @Override
+ public AuthorRecord value1(Integer value) {
+ setId(value);
+ return this;
+ }
+
+ @Override
+ public AuthorRecord value2(String value) {
+ setFirstName(value);
+ return this;
+ }
+
+ @Override
+ public AuthorRecord value3(String value) {
+ setLastName(value);
+ return this;
+ }
+
+ @Override
+ public AuthorRecord value4(Integer value) {
+ setAge(value);
+ return this;
+ }
+
+ @Override
+ public AuthorRecord values(Integer value1, String value2, String value3, Integer value4) {
+ value1(value1);
+ value2(value2);
+ value3(value3);
+ value4(value4);
+ return this;
+ }
+
+ // -------------------------------------------------------------------------
+ // Constructors
+ // -------------------------------------------------------------------------
+
+ /**
+ * Create a detached AuthorRecord
+ */
+ public AuthorRecord() {
+ super(Author.AUTHOR);
+ }
+
+ /**
+ * Create a detached, initialised AuthorRecord
+ */
+ public AuthorRecord(Integer id, String firstName, String lastName, Integer age) {
+ super(Author.AUTHOR);
+
+ set(0, id);
+ set(1, firstName);
+ set(2, lastName);
+ set(3, age);
+ }
+}
diff --git a/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudLiveTest.java b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudLiveTest.java
new file mode 100644
index 0000000000..d41344c08e
--- /dev/null
+++ b/persistence-modules/jooq/src/test/java/com/baeldung/jooq/CrudLiveTest.java
@@ -0,0 +1,257 @@
+package com.baeldung.jooq;
+
+import com.baeldung.jooq.model.tables.Article;
+import com.baeldung.jooq.model.tables.Author;
+import com.baeldung.jooq.model.tables.records.ArticleRecord;
+import org.jooq.DSLContext;
+import org.jooq.Field;
+import org.jooq.Record;
+import org.jooq.Result;
+import org.jooq.SQLDialect;
+import org.jooq.impl.DSL;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+
+import static com.baeldung.jooq.Crud.delete;
+import static com.baeldung.jooq.Crud.getAll;
+import static com.baeldung.jooq.Crud.getFields;
+import static com.baeldung.jooq.Crud.getOne;
+import static com.baeldung.jooq.Crud.save;
+import static com.baeldung.jooq.Crud.update;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class CrudLiveTest {
+
+ static DSLContext context;
+
+ @BeforeClass
+ public static void setup() throws SQLException {
+ Connection conn = DriverManager.getConnection("jdbc:h2:mem:tes;INIT=CREATE SCHEMA IF NOT EXISTS \"public\"");
+ context = DSL.using(conn, SQLDialect.H2);
+
+ context.createTable(Author.AUTHOR)
+ .columns(
+ Author.AUTHOR.ID,
+ Author.AUTHOR.FIRST_NAME,
+ Author.AUTHOR.LAST_NAME,
+ Author.AUTHOR.AGE
+ )
+ .execute();
+ context.createTable(Article.ARTICLE)
+ .columns(
+ Article.ARTICLE.ID,
+ Article.ARTICLE.TITLE,
+ Article.ARTICLE.DESCRIPTION,
+ Article.ARTICLE.AUTHOR_ID
+ )
+ .execute();
+ }
+
+ @Before
+ public void cleanup() {
+ context.truncateTable(Article.ARTICLE)
+ .execute();
+ context.truncateTable(Author.AUTHOR)
+ .execute();
+ }
+
+ @Test
+ public void givenArticleRecord_whenSave_thenNewRecordInDb() {
+ // given
+ ArticleRecord article = article();
+
+ // when
+ save(article);
+
+ // then
+ ArticleRecord savedArticle = getOne(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+ assertEquals(savedArticle.getId().intValue(), 1);
+ assertEquals(savedArticle.getTitle(), "jOOQ examples");
+ assertEquals(savedArticle.getDescription(), "A few examples of jOOQ CRUD operations");
+ assertEquals(savedArticle.getAuthorId().intValue(), 1);
+ }
+
+ @Test
+ public void givenArticleRecord_whenGetAll_thenValidOneRecord() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ // when
+ Result articles = getAll(
+ context,
+ Article.ARTICLE
+ );
+
+ // then
+ assertEquals(articles.size(), 1);
+
+ Record record = articles.get(0);
+ ArticleRecord savedArticle = record.into(Article.ARTICLE);
+
+ assertEquals(savedArticle.getId().intValue(), 1);
+ assertEquals(savedArticle.getTitle(), "jOOQ examples");
+ assertEquals(savedArticle.getDescription(), "A few examples of jOOQ CRUD operations");
+ assertEquals(savedArticle.getAuthorId().intValue(), 1);
+ }
+
+ @Test
+ public void givenArticleRecord_whenGetOnlyTitles_thenValidOneValue() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ // when
+ Result articles = getFields(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.TITLE
+ );
+
+ // then
+ assertEquals(articles.size(), 1);
+
+ Record record = articles.get(0);
+ ArticleRecord savedArticle = record.into(Article.ARTICLE);
+
+ assertNull(savedArticle.getId());
+ assertEquals(savedArticle.getTitle(), "jOOQ examples");
+ assertNull(savedArticle.getDescription());
+ assertNull(savedArticle.getAuthorId());
+ }
+
+ @Test
+ public void givenArticleRecord_whenGetOne_thenValidRecord() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ // when
+ ArticleRecord savedArticle = getOne(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+
+ // then
+ assertEquals(savedArticle.getId().intValue(), 1);
+ assertEquals(savedArticle.getTitle(), "jOOQ examples");
+ assertEquals(savedArticle.getDescription(), "A few examples of jOOQ CRUD operations");
+ assertEquals(savedArticle.getAuthorId().intValue(), 1);
+ }
+
+ @Test
+ public void givenArticleRecord_whenUpdateById_thenChangedValuesDbTable() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ HashMap, String> updateFields = new HashMap<>();
+ updateFields.put(Article.ARTICLE.TITLE, "new title");
+ updateFields.put(Article.ARTICLE.DESCRIPTION, "new description");
+
+ // when
+ update(
+ context,
+ Article.ARTICLE,
+ updateFields,
+ Article.ARTICLE.ID.eq(1)
+ );
+
+ // then
+ ArticleRecord updatedArticle = getOne(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+ assertEquals(updatedArticle.getId().intValue(), 1);
+ assertEquals(updatedArticle.getTitle(), "new title");
+ assertEquals(updatedArticle.getDescription(), "new description");
+ assertEquals(updatedArticle.getAuthorId().intValue(), 1);
+ }
+
+ @Test
+ public void givenArticleRecord_whenUpdate_thenChangedValuesDbTable() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ article.setTitle("new title");
+ article.setDescription("new description");
+
+ // when
+ update(article);
+
+ // then
+ ArticleRecord updatedArticle = getOne(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+ assertEquals(updatedArticle.getId().intValue(), 1);
+ assertEquals(updatedArticle.getTitle(), "new title");
+ assertEquals(updatedArticle.getDescription(), "new description");
+ assertEquals(updatedArticle.getAuthorId().intValue(), 1);
+ }
+
+ @Test
+ public void givenArticleRecord_whenDelete_thenEmptyDbTable() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ // when
+ delete(article);
+
+ // then
+ Result articles = getAll(
+ context,
+ Article.ARTICLE
+ );
+ assertTrue(articles.isEmpty());
+ }
+
+ @Test
+ public void givenArticleRecord_whenDeleteById_thenEmptyDbTable() {
+ // given
+ ArticleRecord article = article();
+ save(article);
+
+ // when
+ delete(
+ context,
+ Article.ARTICLE,
+ Article.ARTICLE.ID.eq(1)
+ );
+
+ // then
+ Result articles = getAll(
+ context,
+ Article.ARTICLE
+ );
+ assertTrue(articles.isEmpty());
+ }
+
+ private ArticleRecord article() {
+ ArticleRecord article = context.newRecord(Article.ARTICLE);
+ article.setId(1);
+ article.setTitle("jOOQ examples");
+ article.setDescription("A few examples of jOOQ CRUD operations");
+ article.setAuthorId(1);
+
+ return article;
+ }
+
+}
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index def2deb941..590e5da76e 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -39,6 +39,7 @@
java-jpa-2
java-mongodb
jnosql
+ jooq
jpa-hibernate-cascade-type
liquibase
orientdb