Hibernate 静态元模型生成器注解处理器

作者:    |      

Steve 在他的 Hibernate 3.5.0 Beta2 博客条目 中简要提到了 Hibernate 静态元模型生成器注解处理器。现在是时候更深入地了解一下这个注解处理器实际上做了什么。

类型安全的 Criteria API

让我们先看看 JPA 2 的新特性之一 - 类型安全的 Criteria API。这个新 API 的关键是为其相应的托管实体生成的元模型类。这些元模型类允许构建基于对象的查询。让我们看一个例子

@Entity public class Order {
    @Id 
    Integer id;
    @ManyToOne 
    Customer customer;
    @OneToMany 
    Set<Item> items;
    BigDecimal totalCost;
    ...
}

在上面的例子中,我们有一个托管实体 Order,它有一个 id、一个指向客户的引用、一个订单项列表和总成本。相应的元模型类看起来像这样

@StaticMetamodel(Order.class)
public class Order_ {
    public static volatile SingularAttribute<Order, Integer> id;
    public static volatile SingularAttribute<Order, Customer> customer;
    public static volatile SetAttribute<Order, Item> items;
    public static volatile SingularAttribute<Order, BigDecimal> totalCost;
}

拥有这样的元模型类允许进行如下形式的查询

CriteriaBuilder cb = ordersEntityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class)
	.join(Order_.orderItems);
cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ) 
	.distinct(true);

在这里我不想深入探讨实际的 Criteria API。有关更多信息,请参考 JSR-317。相反,我想回答如何生成这些元模型类的问题。当然,开发者可以手动维护它们,但这几乎是没有生产力的。更好的解决方案是利用自 Java 6 起官方可用的 注解处理 功能。在 Java 6 中,javac 的行为与 Java 5 中的 apt 命令类似。这是由 JSR-269 规定的。

Hibernate 静态元模型生成器

Hibernate 静态元模型生成器是一个注解处理器的实现,其任务是为实体创建静态元模型类(如上例所示)。以下我将展示如何将注解处理器集成到您的构建环境中。好消息是,在大多数情况下,只要注解处理器 jar 文件在类路径中,注解处理器就会自动运行。这是由于 Java 的 服务提供者 合同以及 Hibernate 静态元模型生成器 jar 文件包含以下文件的事实:javax.annotation.processing.ProcessorMETA-INF/servicesorg.hibernate.jpamodelgen.JPAMetaModelEntityProcessor列为注解处理器。

Maven

有几种方法可以将注解处理器作为Maven构建的一部分运行。如果你使用的是JDK 6编译器且注解处理器jar文件位于类路径中,它将自动运行。如果你类路径中存在多个注解处理器,你可以显式地将processor选项传递给编译插件

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <compilerArguments>
        	<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
        </compilerArguments>
    </configuration>
</plugin>

maven-compiler-plugin方法的缺点是,当前maven编译插件不允许指定多个编译器参数(MCOMPILER-62),并且来自Messager API的消息被抑制(MCOMPILER-66)。一种更好的方法是禁用编译插件的注解处理

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <compilerArgument>-proc:none</compilerArgument>
    </configuration>
</plugin>

并使用maven-annotation-plugin进行注解处理(你将需要以下额外的maven仓库 - maven-annotation-pluginjfrog

<plugin>
    <groupId>org.bsc.maven</groupId>
    <artifactId>maven-processor-plugin</artifactId>
    <executions>
        <execution>
            <id>process</id>
            <goals>
                <goal>process</goal>
            </goals>
            <phase>generate-sources</phase>
            <configuration>
                <!-- source output directory -->
                <outputDirectory>target/metamodel</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.3</version>
    <executions>
        <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>target/metamodel</source>
                </sources>
            </configuration>
        </execution>
    </executions>
</plugin>

最后,但同样重要的是,也可以使用antrun-plugin来运行注解处理器。这种方法可以在这里看到。

Ant

如前所述,在Java 6环境中,注解处理器将自动运行。如果你想显式配置处理器或禁用它,可以使用Javac Taskcompilerarg选项。支持的命令行选项列表在这里

Eclipse

当然,你希望在你的IDE中也可用注解处理。在Eclipse中(至少从最新的Galileo版本开始),在Java Compiler下存在一个额外的配置部分,你可以在此配置注解处理的各个方面。只需勾选“启用注解处理”选项,配置生成的源代码目录,最后将Hibernate静态元模型生成器和JPA 2 jar文件添加到工厂路径。

Idea

Idea还没有为注解处理提供明确的配置部分。相反,你必须依赖Hibernate静态元模型生成器在类路径中且你使用的是Java 6编译器时注解处理将自动发生。然而,你可以在“编译器 - Java编译器”部分下指定额外的编译器命令行选项。

反馈

希望这可以帮助你开始使用Hibernate静态元模型生成器。得到一些反馈将非常棒。源代码目前是Hibernate svn存储库的一部分。trunk是http://anonsvn.jboss.org/repos/hibernate/jpamodelgen/trunk/。jar文件的最新快照可以从JBoss快照存储库检索。错误应该报告在METAGEN

享受吧!


返回顶部