ITEEDU

19.2. 代码生成(Code Generation)

Hibernate代码生成器可以用来为Hibernate映射文件生成Java实现类的骨架。这个工具在Hibernate Extensions发行包中提供(需要单独下载)。

hbm2java解析映射文件,生成可工作的Java源代码文件。使用hbm2java,你可以“只”提供.hbm文件,不用担心要去手工编写Java文件。

java -cp hibernate_classpaths net.sf.hibernate.tool.hbm2java.CodeGenerator options mapping_files

Table 19.5. 代码生成器命令行选项

选项 说明
--output=output_dir 生成代码输出的根目录
--config=config_file 可选的hvm2java配置文件

19.2.1. 配置文件(可选)

配置文件提供了配置生成源代码的多个"渲染器(renders)"的途径,也可以声明在全局范围生效的<meta>属性。详情请参见<meta>属性的部分。

<codegen>
    <meta attribute="implements">codegen.test.IAuditable</meta>
    <generate renderer="net.sf.hibernate.tool.hbm2java.BasicRenderer"/>
    <generate
        package="autofinders.only"
        suffix="Finder"
        renderer="net.sf.hibernate.tool.hbm2java.FinderRenderer"/>
</codegen>

这个配置文件声明了一个全局的meta(元)属性“implements”,指定了两个渲染器,默认渲染器(BadicRender)和生成Finder(参见下面的“基本Finder 生成器”)的渲染器。

定义第二个渲染器需要一个包名和后缀属性。

包名属性指定生成后的源代码应该保存的位置,覆盖在.hbm文件中指定的包范围。

后缀属性指定生成的文件的后缀。比如说,如果有一个Foo.java文件,应该变成FooFinder.java。

19.2.2. meta属性

<meta>标签时对hbm.xml文件进行的简单注解,工具可以用这个位置来保存/阅读和Hibernate内核不是直接相关的一些信息。

你可以用<meta>标签来告诉hbm2java只生成"protectd"

下面的例子:

<class name="Person">
    <meta attribute="class-description">
        Javadoc for the Person class
        @author Frodo
    </meta>
    <meta attribute="implements">IAuditable</meta>
    <id name="id" type="long">
        <meta attribute="scope-set">protected</meta>
        <generator class="increment"/>
    </id>
    <property name="name" type="string">
        <meta attribute="field-description">The name of the person</meta>
    </property>
</class>

会生成类似下面的输出(为了有助于理解,节选部分代码)。注意Javadoc注释和声明成protected的set方法:

// default package

import java.io.Serializable;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/** 
 *         Javadoc for the Person class
 *         @author Frodo
 *     
 */
public class Person implements Serializable, IAuditable {

    /** identifier field */
    public Long id;

    /** nullable persistent field */
    public String name;

    /** full constructor */
    public Person(java.lang.String name) {
        this.name = name;
    }

    /** default constructor */
    public Person() {
    }

    public java.lang.Long getId() {
        return this.id;
    }

    protected void setId(java.lang.Long id) {
        this.id = id;
    }

    /** 
     * The name of the person
     */
    public java.lang.String getName() {
        return this.name;
    }

    public void setName(java.lang.String name) {
        this.name = name;
    }

}

Table 19.6. 支持的meta标签

属性 说明
class-description 插入到类的javadoc说明去
field-description 插入到field/property的javadoc说明去
interface 如果是true,生成interface而非class
implements 类要实现的接口
extends 类要继承的超类(若是subclass,则忽略该属性)
generated-class 重新指定要生成的类名
scope-class class的scope
scope-set set方法的scope
scope-get get方法的scope
scope-field 实际属性字段(field)的scope
use-in-tostring 在toString()中包含此属性
bound 为属性增加propertyChangeListener支持
constrained 为属性增加vetoChangeListener支持
gen-property 如果是false,不会生成属性(谨慎使用)
property-type 覆盖属性的默认值.如果值是标签,则指定一个具体的类型而非Object(Use this with any tag's to specify the concrete type instead of just Object.)
finder-method 参见下面的"Basic finder generator"
session-method 参见下面的"Basic finder generator"

通过<meta>标签定义的属性在一个hbm.xml文件中是默认"继承"的。

这究竟是什么意思?如果你希望你所有的类都实现IAuditable接口,那么你只需要加一个<meta attribute="implements">IAuditable</meta> 在你hml.xml文件的开头,就在<hibernate-mapping>后面。现在所有在hbm.xml文件中定义的类都会实现IAuditable了!(除了那些也特别指定了"implements"元属性的类,因为本地指定的元标签总是会覆盖任何继承的元标签)。

注意,这条规则对所有 的<meta>标签都有效。也就是说它可以用来指定所有的字段都被声明成protected的,而非默认的private。这可以通过在<class>后面<meta attribute="scope-field">protected</meta>指定,那么这个类所有的field都会变成protected。

如果你不想让<meta>标签继承,你可以简单的在标签属性上指明inherit="false",比如<meta attribute="scope-class" inherit="false">public abstract</meta>,这样"class-scope"就只会对当前类起作用,不会对其子类生效。

19.2.3. 基本的finder生成器(Basic finder generator)

目前可以让hbm2java为Hibernate属性生成基本的finder。这需要在hbm.xml文件中做两件事情。

首先是要标记出你希望生成finder的字段。你可以通过在property标签中的meta 块来定义:

<property name="name" column="name" type="string">
     <meta attribute="finder-method">findByName</meta>
</property>

find方法的名字就是meta标签中间的文字。

第二件事是为hbm2java建立下面格式的配置文件:

<codegen>
    <generate renderer="net.sf.hibernate.tool.hbm2java.BasicRenderer"/>
    <generate suffix="Finder" renderer="net.sf.hibernate.tool.hbm2java.FinderRenderer"/>
</codegen>

然后用参数去调用:hbm2java --config=xxx.xml,xxx.xml就是你刚才创建的配置文件的名字。

有个可选的参数,作为一个在class级别的meta标签,格式如下:

<meta attribute="session-method">
    com.whatever.SessionTable.getSessionTable().getSession();
</meta>

他是用来管理你如何使用Thread Local Session模式(在Hibernate 网站的Design Patterns部分有文档)得到session的。

19.2.4. 基于Velocity的渲染器/生成器(Velocity based renderer/generator)

目前可以使用velocity作为渲染机制的一个替代方案。下面的config.xml文件显示了如果配置hbm2java来使用velocity渲染器。

    <codegen>
     <generate renderer="net.sf.hibernate.tool.hbm2java.VelocityRenderer">
      <param name="template">pojo.vm</param>
     </generate>
    </codegen>

名为template的参数是指向你希望你使用velocity macro文件的资源路径。这个文件必须在hbm2java的classpath中。所以要记住把pojo.vm所在的路径加入到你ant任务或者shell脚本中去。(默认的位置是./tools/src/velocity)

注意,当前的pojo.vm只生成java beans最基本的部分。他还没有默认的渲染器那么完整,也没有那么多功能——特别是大部分meta标签还不支持。