修改jOOQ codegen默认生成类策略

本文介绍如何通过自定义jOOQ Codegen策略解决字段名转换问题,确保生成的Java类成员名与数据库表完全一致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用默认生成类策略

项目中采用了jOOQ作为ORM框架,并使用jOOQ codegen生成Table,Record和PO。

codegen使用说明请见这里。codegen的gradle配置请见这里

表结构:

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配置:

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将数据库中的下划线自动转换为了驼峰命名。

因为要兼容老接口,必须将userName改为user_name格式。

修改默认策略

打开上面gradle配置中的xmlns定义URL,发现Generator中有strategy配置项:

<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文件如下:

        // 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等:

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 ...
}

 

转载于:https://my.oschina.net/landas/blog/1573586

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值