JOOQ provides a sql-intuive way to write typesafe sql queries in Java.

Minuteproject 4 JOOQ aims at providing the JOOQ framework a reverse-engineering solution to get customized artefacts.

Although jOOQ is delivered with a generator that do reverse-engineering from database already, there is an ongoing collaboration between MinuteProject and JOOQ to
  • cover jOOQ generator features
  • while in the meantime benefiting of MinuteProject features.

MinuteProject 4 JOOQ will provide
  • enrichment feature
    • aliasing of table name, columns, enumeration values
    • declarative conventions
    • structure manipulation
      • add primary key, foreign key
  • updatable code (generated code can be modified and modification are kept)
  • generate any text based artifact
  • provide a workspace to plug jOOQ template and dependencies

The generated artefacts are
  • At model level
    • jOOQ model
    • jOOQ model factory
    • jOOQ keys
    • jOOQ tables
    • jOOQ routines
  • At entity level
    • jOOQ entity
    • jOOQ record
    • jOOQ entity unit test
  • At stored-procedure level
    • jOOQ stored-procedure
  • At column level
    • jOOQ enumerations
  • At application level
    • jOOQ pom.xml
    • jOOQ native generator input properties file.

Generation Step | Configuration | Generated code | Extending and packaging

Generation Step

The 'Generation step' consists of configuring MP kernel either via a configuration file or via the console.

Prequisites

Have Java 6 setup.
Download MinuteProjectlast version.
Check that your database connection is available

Generation Via the console

  1. Start the MP console (<MP_HOME>/bin/start-console.(cmd/sh). How to use the console.
  2. Fill the connection information to the datamodel
  3. Fill the model general information (model, package names, version primary key policy, scope).
  4. Choose JOOQ target
  5. Click generate

Generation Via the configuration file and command line

An example can be found <MP_HOME>/demo/config/mp-config-JOOQ-tech.xml and <MP_HOME>/demo/config/mp-config-JOOQ.xml
mp-config-JOOQ-tech.xml references the jOOQ acceptance test database from jooq site here
This database has to be installed locally and accessible.
In the configuration the connection parameters are
  • URL jdbc:mysql://127.0.0.1:3306/jooq_tech
  • username=root
  • password=mysql
mp-config-JOOQ.xml references the shipped petshop database (<MP_HOME>/sample).

To run it, execute demo-JOOQ-tech.(cmd/sh), demo-JOOQ.(cmd/sh)


Configuration

mp-config-JOOQ-tech configuration
<!DOCTYPE root>
<generator-config>
    <configuration>
        <conventions>
            <target-convention type="enable-updatable-code-feature" />
        </conventions>
        <model name="jooqtech" version="1.0" package-root="net.sf.mp.demo.jooq">
            <data-model>
                <driver name="mysql" version="5.1.16" groupId="mysql"
                    artifactId="mysql-connector-java"></driver>
                <fileSource name="jooqtech" dir="c:/MinuteProject/data">
                </fileSource>
                <dataSource>
                    <driverClassName>org.gjt.mm.mysql.Driver</driverClassName>
                    <url>jdbc:mysql://127.0.0.1:3306/jooq_tech</url>
                    <username>root</username>
                    <password>mysql</password>
                </dataSource>
                <schema>jooq_tech</schema>
            </data-model>
            <function-model />
            <business-model>
                <enrichment>
                    <conventions>
                        <table-default-primary-key-convention
                            type="apply-default-primary-key-otherwise-first-one"
                            default-primary-key-names="ID" />
                        <view-primary-key-convention
                            type="apply-default-primary-key-otherwise-first-one"
                            default-primary-key-names="ID">
                        </view-primary-key-convention>
                    </conventions>
                    <entity name="T_BOOK">
                        <field name="STATUS">
                            <property tag="checkconstraint" alias="my_book_status">
                                <property name="SOLD OUT" />
                                <property name="ORDERED" />
                                <property name="IN HOUSE" value="on stock" />
                                <property name="abstract" />
                            </property>
                        </field>
                    </entity>
                    <entity name="V_BOOK">
                        <field name="STATUS">
                            <property tag="checkconstraint">
                                <property name="SOLD OUT" />
                                <property name="ORDERED" />
                                <property name="IN HOUSE" value="ON STOCK" />
                            </property>
                        </field>
                    </entity>
                </enrichment>
            </business-model>
        </model>
        <targets catalog-entry="JOOQ"/>
    </configuration>
</generator-config>
The main points are:
Enabling updatable feature: the code containing updatable part will be handled
<target-convention type="enable-updatable-code-feature" />
Adding the schema: use for jooq model class
<schema>jooq_tech</schema>
Function model: this indicates to take into account storeprocedure (by default they are excluded from the generator)
<function-model />
Enrichment
  • convention for primary key
  • add checkcontraint on entity fields (table or view) with alias for enum class generation

Choose jOOQ version
<property name="jooq-version" value="2.0.4"></property>

Generated code

Structure

Jooq-tech project structure
jooq-structure1.png

Jooq-tech table structure tables artifacts and records
jooq-structure2.png

Details

Enumeration

MyBookStatus sample
/**
 * This class is generated by minuteproject 4 jOOQ
 */
package net.sf.mp.demo.jooq.jooqtech.enums.jooqtech;
 
import java.util.ArrayList;
import java.util.List;
 
//MP-MANAGED-ADDED-AREA-BEGINNING @import@
//MP-MANAGED-ADDED-AREA-ENDING @import@
 
//MP-MANAGED-ADDED-AREA-BEGINNING @class-annotation@
//MP-MANAGED-ADDED-AREA-ENDING @class-annotation@
@javax.annotation.Generated(value    = {"http://www.jooq.org", "$jooqVersion"},
                            comments = "This class is generated by minuteproject 4 jOOQ")
 
public enum MyBookStatus implements org.jooq.EnumType {
 
    SOLD_OUT("SOLD OUT"),
    ORDERED("ORDERED"),
    IN_HOUSE("on stock"),
    ABSTRACT("abstract");
 
    private final String literal;
 
    private MyBookStatus(String literal) {
        this.literal = literal;
    }
 
    @Override
    public String getName() {
        return "t_book_STATUS";
    }
 
    @Override
    public String getLiteral() {
        return literal;
    }
 
    public static MyBookStatus fromValue(String v) {
        for (MyBookStatus c : MyBookStatus.values()) {
            if (c.literal.equals(v)) {
                return c;
            }
        }
        return null; //no IllegalArgEx thrown there, null returned on purpose.
    }
 
    /**
    * Return a list that contains all the enumeration values
    * @return List<MyBookStatus> the that contains all the enumeration values
    */
    public static List<MyBookStatus> getList() {
        List<MyBookStatus> list = new ArrayList<MyBookStatus>();
        for (MyBookStatus c : MyBookStatus.values()) {
           list.add(c);
        }
        return list;
    }
 
    /**
    * @param value
    * @return boolean : true if the value exist in the enum
    */
    public static boolean contains (String value) {
       for (MyBookStatus c : MyBookStatus.values()) {
          if (c.toString().equals(value))
             return true;
          }
       return false;
    }
 
    public static boolean containsValue (String value) {
        for (MyBookStatus c : MyBookStatus.values()) {
           if (c.literal.equals(value))
              return true;
           }
        return false;
    }
 
    public boolean equals (String s) {
        if (s==null) return false;
        return s.equals(literal);
    }
 
//MP-MANAGED-ADDED-AREA-BEGINNING @implementation@
//MP-MANAGED-ADDED-AREA-ENDING @implementation@
 
}
 
Main points are:
Alias is used instead of the default name of the enum class (MyBookStatus)
Enumeration name and value can differ thanks to enrichment (Java conventions are not tight to DB one but mapped)
Code between MP-MANAGED-ADDED-AREA is alterable

Routine

Routine F317 sample
/**
 * This class is generated by jOOQ
 */
package net.sf.mp.demo.jooq.jooqtech.routines.jooqtech;
 
import org.jooq.Field;
import org.jooq.Parameter;
import org.jooq.impl.AbstractRoutine;
/**
 * This class is generated by jOOQ.
 */
@javax.annotation.Generated(value    = {"http://www.jooq.org", "2.0.2"},
                            comments = "This class is generated by jOOQ")
public class F317 extends AbstractRoutine<java.lang.Integer> {
 
    private static final long serialVersionUID = 123456789;
 
    /**
     * An uncommented item
     */
    public static final Parameter<java.lang.Integer> RETURN_VALUE =
       createParameter("RETURN_VALUE", org.jooq.impl.SQLDataType.INTEGER);
 
     /**
     * An uncommented item
     */
    public static final Parameter<java.lang.Integer> P1 =
       createParameter("p1", org.jooq.impl.SQLDataType.INTEGER); //org.jooq.impl.SQLDataType.INTEGER
 
     /**
     * An uncommented item
     */
    public static final Parameter<java.lang.Integer> P2 = createParameter("p2", org.jooq.impl.SQLDataType.INTEGER);
     /**
     * An uncommented item
     */
    public static final Parameter<java.lang.Integer> P3 = createParameter("p3", org.jooq.impl.SQLDataType.INTEGER);
 
     /**
     * An uncommented item
     */
    public static final Parameter<java.lang.Integer> P4 = createParameter("p4", org.jooq.impl.SQLDataType.INTEGER);
 
 
    /**
     * Create a new routine call instance
     */
    public F317() {
        super(org.jooq.SQLDialect.MYSQL, "f317", net.sf.mp.demo.jooq.jooqtech.Jooqtech.JOOQTECH,
              org.jooq.impl.SQLDataType.INTEGER);
        setReturnParameter(RETURN_VALUE);
         addInParameter(P1);
         addInParameter(P2);
         addInParameter(P3);
         addInParameter(P4);
    }
 
     /**
     * Set the <code>p1</code> parameter to the routine
     */
    public void setP1(java.lang.Integer value) {
        setValue(P1, value);
    }
 
    /**
     * Set the <code>p1</code> parameter to the function
     * <p>
     * Use this method only, if the function is called as a {@link org.jooq.Field} in a {@link org.jooq.Select} statement!
     */
    public void setP1(Field<java.lang.Integer> field) {
        setField(P1, field);
    }
 
     /**
     * Set the <code>p2</code> parameter to the routine
     */
    public void setP2(java.lang.Integer value) {
        setValue(P2, value);
    }
 
    /**
     * Set the <code>p2</code> parameter to the function
     * <p>
     * Use this method only, if the function is called as a {@link org.jooq.Field} in a {@link org.jooq.Select} statement!
     */
    public void setP2(Field<java.lang.Integer> field) {
        setField(P2, field);
    }
 
     /**
     * Set the <code>p3</code> parameter to the routine
     */
    public void setP3(java.lang.Integer value) {
        setValue(P3, value);
    }
 
    /**
     * Set the <code>p3</code> parameter to the function
     * <p>
     * Use this method only, if the function is called as a {@link org.jooq.Field} in a {@link org.jooq.Select} statement!
     */
    public void setP3(Field<java.lang.Integer> field) {
        setField(P3, field);
    }
 
     /**
     * Set the <code>p4</code> parameter to the routine
     */
    public void setP4(java.lang.Integer value) {
        setValue(P4, value);
    }
 
    /**
     * Set the <code>p4</code> parameter to the function
     * <p>
     * Use this method only, if the function is called as a {@link org.jooq.Field} in a {@link org.jooq.Select} statement!
     */
    public void setP4(Field<java.lang.Integer> field) {
        setField(P4, field);
    }
 
 
}

Table

Table TBook sample
/**
 * This class is generated by minuteproject 4 jOOQ
 */
package net.sf.mp.demo.jooq.jooqtech.tables;
 
import net.sf.mp.demo.jooq.jooqtech.tables.records.TBookRecord;
import net.sf.mp.demo.jooq.jooqtech.Jooqtech;
import net.sf.mp.demo.jooq.jooqtech.Keys;
 
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.ForeignKey;
import java.util.List;
import java.util.Arrays;
 
//MP-MANAGED-ADDED-AREA-BEGINNING @import@
//MP-MANAGED-ADDED-AREA-ENDING @import@
 
//MP-MANAGED-ADDED-AREA-BEGINNING @class-annotation@
//MP-MANAGED-ADDED-AREA-ENDING @class-annotation@
@javax.annotation.Generated(value    = {"http://www.jooq.org", "2.0.1"},
                            comments = "This class is generated by minuteproject 4 jOOQ")
public class TBook extends org.jooq.impl.UpdatableTableImpl <TBookRecord> {
 
    private static final long serialVersionUID = 123456789;
 
    /**
     * The singleton instance of TBook
     */
    public static final TBook __T_BOOK = new TBook();
 
    /**
     * The class holding records for this type
     */
    private static final Class<TBookRecord> __RECORD_TYPE = TBookRecord.class;
 
    /**
     * The class holding records for this type
     */
    @Override
    public Class<TBookRecord> getRecordType() {
        return __RECORD_TYPE;
    }
 
 
     // pk ID
 
    /**
     * An uncommented item
     *
     * PRIMARY KEY ID
     */
    public final TableField<TBookRecord, java.lang.Integer> ID = createField("ID", org.jooq.impl.SQLDataType.INTEGER, this);
 
     /**
     * TITLE mapping for TITLE
     */
    public final TableField<TBookRecord, java.lang.String> TITLE =
       createField("TITLE", org.jooq.impl.SQLDataType.LONGVARCHAR, this);
     /**
     * PUBLISHED_IN mapping for PUBLISHED_IN
     */
    public final TableField<TBookRecord, java.lang.Integer> PUBLISHED_IN =
       createField("PUBLISHED_IN", org.jooq.impl.SQLDataType.INTEGER, this);
     /**
     * CONTENT_TEXT mapping for CONTENT_TEXT
     */
    public final TableField<TBookRecord, java.lang.String> CONTENT_TEXT =
        createField("CONTENT_TEXT", org.jooq.impl.SQLDataType.LONGVARCHAR, this);
     /**
     * CONTENT_PDF mapping for CONTENT_PDF
     */
    public final TableField<TBookRecord, byte[]> CONTENT_PDF =
       createField("CONTENT_PDF", org.jooq.impl.SQLDataType.LONGVARBINARY, this);
     /**
     * STATUS mapping for STATUS
     */
    public final TableField<TBookRecord, net.sf.mp.demo.jooq.jooqtech.enums.jooqtech.MyBookStatus> STATUS =
       createField("STATUS", org.jooq.impl.SQLDataType.CHAR.asEnumDataType(
         net.sf.mp.demo.jooq.jooqtech.enums.jooqtech.MyBookStatus.class), this);
 
       /**
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.authorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public final TableField<TBookRecord, java.lang.Integer> AUTHOR_ID =
       createField("AUTHOR_ID", org.jooq.impl.SQLDataType.INTEGER, this);
 
       /**
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.coAuthorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public final TableField<TBookRecord, java.lang.Integer> CO_AUTHOR_ID =
       createField("co_author_id", org.jooq.impl.SQLDataType.INTEGER, this);
 
       /**
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.detailsId]
     * REFERENCES TBookDetails [TBookDetails.id]
     * </pre></code>
     */
    public final TableField<TBookRecord, java.lang.Integer> DETAILS_ID =
       createField("DETAILS_ID", org.jooq.impl.SQLDataType.INTEGER, this);
 
       /**
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.languageId]
     * REFERENCES TLanguage [TLanguage.id]
     * </pre></code>
     */
    public final TableField<TBookRecord, java.lang.Integer> LANGUAGE_ID =
       createField("LANGUAGE_ID", org.jooq.impl.SQLDataType.INTEGER, this);
 
 
    /**
     * No further instances allowed
     */
    private TBook() {
        super("t_book", Jooqtech.JOOQTECH);
    }
 
    /**
     * No further instances allowed
     */
    private TBook(String alias) {
        super(alias, Jooqtech.JOOQTECH, TBook.__T_BOOK);
    }
 
    @Override
    public org.jooq.UniqueKey<TBookRecord> getMainKey() {
        return Keys.KEY_t_book_PRIMARY;
    }
 
    @Override
    @SuppressWarnings("unchecked")
    public java.util.List<UniqueKey<TBookRecord>> getKeys() {
        return java.util.Arrays.<UniqueKey<TBookRecord>>asList(Keys.KEY_t_book_PRIMARY);
    }
 
    @Override
    public TBook as(java.lang.String alias) {
        return new TBook(alias);
    }
 
//MP-MANAGED-ADDED-AREA-BEGINNING @implementation@
//MP-MANAGED-ADDED-AREA-ENDING @implementation@
 
}
 
Main points are:
Updatable code
Reference is made to enum instead of java sql type when the field is considered as checkconstraint

Record

/**
 * This class is generated by minuteproject 4 jOOQ
 */
package net.sf.mp.demo.jooq.jooqtech.tables.records;
 
import org.jooq.impl.UpdatableRecordImpl;
 
import net.sf.mp.demo.jooq.jooqtech.tables.TBook;
import net.sf.mp.demo.jooq.jooqtech.Jooqtech;
import net.sf.mp.demo.jooq.jooqtech.Keys;
import java.sql.*;
 
//MP-MANAGED-ADDED-AREA-BEGINNING @import@
//MP-MANAGED-ADDED-AREA-ENDING @import@
 
//MP-MANAGED-ADDED-AREA-BEGINNING @class-annotation@
//MP-MANAGED-ADDED-AREA-ENDING @class-annotation@
@javax.annotation.Generated(value    = {"http://www.jooq.org", "2.0.1"},
                            comments = "This class is generated by minuteproject 4 jOOQ")
public class TBookRecord extends UpdatableRecordImpl<net.sf.mp.demo.jooq.jooqtech.tables.records.TBookRecord> {
 
    private static final long serialVersionUID = 123456789;
 
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-pk-jooqtech@
    /**
     * An uncommented item
     *
     * PRIMARY KEY
     */
    public void setId(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.ID, value);
    }
    /**
     * An uncommented item
     *
     * PRIMARY KEY
     */
    public java.lang.Integer getId() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.ID);
    }
//MP-MANAGED-UPDATABLE-ENDING
  //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-child-TBookToBookStoreTBookViaBookId-jooqtech@
    /**
     * An uncommented item
     *
     */
    public java.util.List<net.sf.mp.demo.jooq.jooqtech.tables.records.TBookToBookStoreRecord> fetchTBookToBookStoreTBookViaBookIdList() {
        return create()
            .selectFrom(net.sf.mp.demo.jooq.jooqtech.tables.TBookToBookStore.__T_BOOK_TO_BOOK_STORE)
            .where(net.sf.mp.demo.jooq.jooqtech.tables.TBookToBookStore.__T_BOOK_TO_BOOK_STORE.BOOK_ID
             .equal(getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.ID))) //reference.foreignColumn.alias = BOOK_ID
            .fetch();
    }
 
//MP-MANAGED-UPDATABLE-ENDING
//many2many
 
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-attribute-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.TITLE-jooqtech@
    /**
     * mapping TITLE setter
     */
    public void setTitle(java.lang.String value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.TITLE, value);
    }
 
    /**
     * mapping TITLE getter
     */
    public java.lang.String getTitle() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.TITLE);
    }
 
//MP-MANAGED-UPDATABLE-ENDING
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-attribute-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.PUBLISHED_IN-jooqtech@
    /**
     * mapping PUBLISHED_IN setter
     */
    public void setPublishedIn(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.PUBLISHED_IN, value);
    }
 
    /**
     * mapping PUBLISHED_IN getter
     */
    public java.lang.Integer getPublishedIn() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.PUBLISHED_IN);
    }
 
//MP-MANAGED-UPDATABLE-ENDING
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-attribute-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_TEXT-jooqtech@
    /**
     * mapping CONTENT_TEXT setter
     */
    public void setContentText(java.lang.String value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_TEXT, value);
    }
 
    /**
     * mapping CONTENT_TEXT getter
     */
    public java.lang.String getContentText() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_TEXT);
    }
 
//MP-MANAGED-UPDATABLE-ENDING
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-attribute-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_PDF-jooqtech@
    /**
     * mapping CONTENT_PDF setter
     */
    public void setContentPdf(byte[] value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_PDF, value);
    }
 
    /**
     * mapping CONTENT_PDF getter
     */
    public byte[] getContentPdf() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CONTENT_PDF);
    }
 
//MP-MANAGED-UPDATABLE-ENDING
 //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-attribute-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.STATUS-jooqtech@
    /**
     * mapping STATUS setter
     */
    public void setStatus(net.sf.mp.demo.jooq.jooqtech.enums.jooqtech.MyBookStatus value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.STATUS, value);
    }
 
    /**
     * mapping STATUS getter
     */
    public net.sf.mp.demo.jooq.jooqtech.enums.jooqtech.MyBookStatus getStatus() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.STATUS);
    }
 
//MP-MANAGED-UPDATABLE-ENDING
 
   //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-parent-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.AUTHOR_ID-jooqtech@
    /**
     * setter and mapper in for authorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.authorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public void setAuthorId(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.AUTHOR_ID, value);
    }
 
 
    /**
     * getter and mapper out for authorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.authorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public java.lang.Integer getAuthorId() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.AUTHOR_ID);
    }
 
 
    /**
     * fetcher of associated TAuthor via AuthorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.authorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public net.sf.mp.demo.jooq.jooqtech.tables.records.TAuthorRecord fetchAuthorId() {
        return create()
            .selectFrom(net.sf.mp.demo.jooq.jooqtech.tables.TAuthor.__T_AUTHOR)
            .where(net.sf.mp.demo.jooq.jooqtech.tables.TAuthor.__T_AUTHOR.ID
             .equal(getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.AUTHOR_ID)))
            .fetchOne();
    }
//MP-MANAGED-UPDATABLE-ENDING
   //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-parent-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CO_AUTHOR_ID-jooqtech@
    /**
     * setter and mapper in for coAuthorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.coAuthorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public void setCoAuthorId(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CO_AUTHOR_ID, value);
    }
 
 
    /**
     * getter and mapper out for coAuthorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.coAuthorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public java.lang.Integer getCoAuthorId() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CO_AUTHOR_ID);
    }
 
 
    /**
     * fetcher of associated TAuthor via CoAuthorId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.coAuthorId]
     * REFERENCES TAuthor [TAuthor.id]
     * </pre></code>
     */
    public net.sf.mp.demo.jooq.jooqtech.tables.records.TAuthorRecord fetchCoAuthorId() {
        return create()
            .selectFrom(net.sf.mp.demo.jooq.jooqtech.tables.TAuthor.__T_AUTHOR)
            .where(net.sf.mp.demo.jooq.jooqtech.tables.TAuthor.__T_AUTHOR.ID
             .equal(getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.CO_AUTHOR_ID)))
            .fetchOne();
    }
//MP-MANAGED-UPDATABLE-ENDING
   //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-parent-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.DETAILS_ID-jooqtech@
    /**
     * setter and mapper in for detailsId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.detailsId]
     * REFERENCES TBookDetails [TBookDetails.id]
     * </pre></code>
     */
    public void setDetailsId(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.DETAILS_ID, value);
    }
 
 
    /**
     * getter and mapper out for detailsId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.detailsId]
     * REFERENCES TBookDetails [TBookDetails.id]
     * </pre></code>
     */
    public java.lang.Integer getDetailsId() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.DETAILS_ID);
    }
 
 
    /**
     * fetcher of associated TBookDetails via DetailsId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.detailsId]
     * REFERENCES TBookDetails [TBookDetails.id]
     * </pre></code>
     */
    public net.sf.mp.demo.jooq.jooqtech.tables.records.TBookDetailsRecord fetchDetailsId() {
        return create()
            .selectFrom(net.sf.mp.demo.jooq.jooqtech.tables.TBookDetails.__T_BOOK_DETAILS)
            .where(net.sf.mp.demo.jooq.jooqtech.tables.TBookDetails.__T_BOOK_DETAILS.ID
             .equal(getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.DETAILS_ID)))
            .fetchOne();
    }
//MP-MANAGED-UPDATABLE-ENDING
   //MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @jooq-record-parent-net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.LANGUAGE_ID-jooqtech@
    /**
     * setter and mapper in for languageId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.languageId]
     * REFERENCES TLanguage [TLanguage.id]
     * </pre></code>
     */
    public void setLanguageId(java.lang.Integer value) {
        setValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.LANGUAGE_ID, value);
    }
 
 
    /**
     * getter and mapper out for languageId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.languageId]
     * REFERENCES TLanguage [TLanguage.id]
     * </pre></code>
     */
    public java.lang.Integer getLanguageId() {
        return getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.LANGUAGE_ID);
    }
 
 
    /**
     * fetcher of associated TLanguage via LanguageId
     * <p>
     * <code><pre>
     * FOREIGN KEY [TBook.languageId]
     * REFERENCES TLanguage [TLanguage.id]
     * </pre></code>
     */
    public net.sf.mp.demo.jooq.jooqtech.tables.records.TLanguageRecord fetchLanguageId() {
        return create()
            .selectFrom(net.sf.mp.demo.jooq.jooqtech.tables.TLanguage.__T_LANGUAGE)
            .where(net.sf.mp.demo.jooq.jooqtech.tables.TLanguage.__T_LANGUAGE.ID.
              equal(getValue(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK.LANGUAGE_ID)))
            .fetchOne();
    }
//MP-MANAGED-UPDATABLE-ENDING
    /**
     * Create a detached TBookRecord
     */
    public TBookRecord() {
        super(net.sf.mp.demo.jooq.jooqtech.tables.TBook.__T_BOOK);
    }
 
//MP-MANAGED-ADDED-AREA-BEGINNING @implementation@
//MP-MANAGED-ADDED-AREA-ENDING @implementation@
 
}
 
Main points are:
Search children and parents

Model specific jooq artifact

5 artifacts JooqTech, JooqTechFactory, Keys, Routines, Tables.

Maven pom

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
      <groupId>net.sf.mp.demo.jooq.jooqtech</groupId>
      <artifactId>jooqtechBackEnd</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>
      <name>jooqtechBackEnd JOOQ implementation</name>
 
    <dependencies>
        <!-- jooq -->
        <dependency>
          <groupId>org.jooq</groupId>
          <!-- artefacts are jooq, jooq-meta, jooq-codegen -->
          <artifactId>jooq</artifactId>
          <version>${jooq.version}</version>
        </dependency>
        <!-- JDBC driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.16</version>
        </dependency>
        <!-- other dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <!-- Force UTF-8 & Java-Version 1.6 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <!--<encoding>utf-8</encoding>-->
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <jooq.version>2.0.1</jooq.version>
    </properties>
 
</project>

JOOQ generator input

jdbc.Driver=org.gjt.mm.mysql.Driver
jdbc.URL=jdbc:mysql://127.0.0.1:3306/jooq_tech
jdbc.User=root
jdbc.Password=mysql
generator.database.input-schema=JOOQ_TECH
generator.database.includes=.*
generator.database.excludes=
generator.generate.master-data-tables=[a list of tables]  // covered in mp by enrichment (individually) or convention
generator.generate.master-data-table-literal.[master data table]=[column used for enum literals]  // cover by field enrichment (constraint)
generator.generate.master-data-table-description.[master data table]=[column used for documentation]  // idem
generator=org.jooq.util.DefaultGenerator
# generator.database=org.jooq.util.mysql.MySQLDatabase
generator.database=org.jooq.util.mysql.MySQLDatabase
generator.generate.relations=true
generator.generate.deprecated=false
generator.target.package=net.sf.mp.demo.jooq.jooqtech
generator.target.directory=../../dev/JOOQ/jooq-tech/
generator.generate.instance-fields=true
generator.generate.unsigned-types=true




Extending and packaging

Extending

The generated artifacts have an updatable nature and since the configuration enable updatable feature, you can add, update, freeze code for each generated artifacts. More information on updatable feature here.

Packaging

Minuteproject generates a default pom.xml with jooq, junit, jdbc driver dependency.
To release, from a command line execute: mvn clean package
This will compile code and run the unit test suite that by default execute a select statement returning the first record for each entity.