修改jOOQ codegen默認生成類策略

使用默認生成類策略

項目中採用了jOOQ做爲ORM框架,並使用jOOQ codegen生成Table,Record和PO。java

codegen使用說明請見這裏。codegen的gradle配置請見這裏mysql

表結構:spring

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

gradle配置:sql

import groovy.xml.MarkupBuilder
import org.jooq.util.GenerationTool
import javax.xml.bind.JAXB

buildscript {
    ext {
        springBootVersion = '1.5.4.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath('mysql:mysql-connector-java:5.1.39')
        classpath('org.jooq:jooq-codegen:3.9.1')
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'

version = '1.0'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

configurations {
    providedRuntime
}

dependencies {
	compile('org.springframework.boot:spring-boot-starter-jooq')
	compile('mysql:mysql-connector-java:5.1.39')
	compile('com.zaxxer:HikariCP:2.6.1')
    compileOnly('org.jooq:jooq-codegen:3.9.1')
}

task jooq_code_generate(type: Task) {
    // Use your favourite XML builder to construct the code generation configuration file
    def writer = new StringWriter()
    def xml = new MarkupBuilder(writer)
            .configuration('xmlns': 'http://www.jooq.org/xsd/jooq-codegen-3.9.0.xsd') {
        jdbc() {
            driver('com.mysql.jdbc.Driver')
            url('jdbc:mysql://${IP}:${PORT}?characterEncoding=UTF-8&allowMultiQueries=true')
            user('${username}')
            password('${passwd}')
        }
        generator() {
            database() {
                name('org.jooq.util.mysql.MySQLDatabase')
                inputSchema('${schema}')
                includes("user")
//                excludes("schema_version")
            }
            generate([:]) {
                pojos true
//                daos true
            }
            target() {
                packageName('com.landas.temp')
                directory('src/main/java')
                encoding("UTF-8")
            }
        }
    }

    // Run the code generator
    doLast {
        GenerationTool.generate(
                JAXB.unmarshal(new StringReader(writer.toString()), 
                                    org.jooq.util.jaxb.Configuration.class)
        )
    }
}

此時運行task,生成的po以下:數據庫

public class User implements Serializable {

    private static final long serialVersionUID = -1585262004;

    private Integer id;
    private String  userName;

    // omitted...
}

可見codegen將數據庫中的下劃線自動轉換爲了駝峯命名。app

由於要兼容老接口,必須將userName改成user_name格式。框架

修改默認策略

打開上面gradle配置中的xmlns定義URL,發現Generator中有strategy配置項:maven

<complexType name="Generator">
  <all>
    <element name="name" type="string" default="org.jooq.util.DefaultGenerator" minOccurs="0" maxOccurs="1"/>
    <element name="strategy" type="tns:Strategy" minOccurs="0" maxOccurs="1"/>
    <element name="database" type="tns:Database" minOccurs="1" maxOccurs="1"/>
    <element name="generate" type="tns:Generate" minOccurs="0" maxOccurs="1"/>
    <element name="target" type="tns:Target" minOccurs="0" maxOccurs="1"/>
  </all>
</complexType>
<complexType name="Strategy">
  <choice>
    <element name="name" type="string" minOccurs="0" maxOccurs="1" default="org.jooq.util.DefaultGeneratorStrategy"/>
    <element name="matchers" type="tns:Matchers" minOccurs="0" maxOccurs="1"/>
  </choice>
</complexType>

查詢jOOQ codegen文檔,發現確實能夠在generator中配置策略。按照文檔教程,自定義了策略類AsInDatabaseStratege,添加到generator中,修改後的gradle文件以下:ide

// omitted ...
        generator() {
            database() {
                name('org.jooq.util.mysql.MySQLDatabase')
                inputSchema('${schema}')
                includes("user")
//                excludes("schema_version")
            }
            strategy() {
                name('com.landas.AsInDatabaseStrategy')
            }
            generate([:]) {
                pojos true
//                daos true
            }
            target() {
                packageName('com.landas.temp')
                directory('src/main/java')
                encoding("UTF-8")
            }
        }
        // omitted ...

AsInDatabaseStratege類以下,注意幾個重寫的方法getJavaMemberName/getJavaSetterName等:spring-boot

import org.jooq.util.DefaultGeneratorStrategy;
import org.jooq.util.Definition;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Landas on 2017/10/17.
 */
public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {

    /**
     * Override this to specifiy what identifiers in Java should look like.
     * This will just take the identifier as defined in the database.
     */
    @Override
    public String getJavaIdentifier(Definition definition) {
        return definition.getOutputName();
    }

    /**
     * Override these to specify what a setter in Java should look like. Setters
     * are used in TableRecords, UDTRecords, and POJOs. This example will name
     * setters "set[NAME_IN_DATABASE]"
     */
    @Override
    public String getJavaSetterName(Definition definition, Mode mode) {
        String name = definition.getOutputName();
        return "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    /**
     * Just like setters...
     */
    @Override
    public String getJavaGetterName(Definition definition, Mode mode) {
        String name = definition.getOutputName();
        return "get" +  name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    /**
     * Override this method to define what a Java method generated from a database
     * Definition should look like. This is used mostly for convenience methods
     * when calling stored procedures and functions. This example shows how to
     * set a prefix to a CamelCase version of your procedure
     */
    @Override
    public String getJavaMethodName(Definition definition, Mode mode) {
        return "call" + org.jooq.tools.StringUtils.toCamelCase(definition.getOutputName());
    }

    /**
     * Override this method to define how your Java classes and Java files should
     * be named. This example applies no custom setting and uses CamelCase versions
     * instead
     */
    @Override
    public String getJavaClassName(Definition definition, Mode mode) {
        return super.getJavaClassName(definition, mode);
    }

    /**
     * Override this method to re-define the package names of your generated
     * artefacts.
     */
    @Override
    public String getJavaPackageName(Definition definition, Mode mode) {
        return super.getJavaPackageName(definition, mode);
    }

    /**
     * Override this method to define how Java members should be named. This is
     * used for POJOs and method arguments
     */
    @Override
    public String getJavaMemberName(Definition definition, Mode mode) {
        return definition.getOutputName();
    }

    /**
     * Override this method to define the base class for those artefacts that
     * allow for custom base classes
     */
    @Override
    public String getJavaClassExtends(Definition definition, Mode mode) {
        return Object.class.getName();
    }

    /**
     * Override this method to define the interfaces to be implemented by those
     * artefacts that allow for custom interface implementation
     */
    @Override
    public List<String> getJavaClassImplements(Definition definition, Mode mode) {
        return Arrays.asList(Serializable.class.getName(), Cloneable.class.getName());
    }

    /**
     * Override this method to define the suffix to apply to routines when
     * they are overloaded.
     *
     * Use this to resolve compile-time conflicts in generated source code, in
     * case you make heavy use of procedure overloading
     */
    @Override
    public String getOverloadSuffix(Definition definition, Mode mode, String overloadIndex) {
        return "_OverloadIndex_" + overloadIndex;
    }
}

注意,這個類直接放在項目中gradle任務運行時是引用不到的,會報找不到類的異常:

Execution failed for task ':jooq_code_generate'.
> java.lang.ClassNotFoundException: com.landas.AsInDatabaseStrategy

爲了讓任務正常運行,須要在項目中新建buildSrc目錄,將自定義的類放到buildSrc的src目錄下,gradle能自動引用到此目錄下的全部類(詳情請查詢gradle手冊)。此時項目結構以下:

buildSrc中的gradle配置以下:

apply plugin: 'groovy'

version=1.0

repositories {
    mavenCentral()
}

dependencies {
    compile('org.jooq:jooq-codegen:3.9.1')
    compile gradleApi()
    compile localGroovy()
}

此時,從新運行 jooq_code_generate 任務,獲得指望的結果:

public class User implements Serializable {

    private Integer id;
    private String  user_name;

    // omitted ...

    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUser_name() {
        return this.user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    // omitted ...
}
相關文章
相關標籤/搜索