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.Processor在META-INF/services将org.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-plugin 和 jfrog)
<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 Task的compilerarg选项。支持的命令行选项列表在这里。
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。
享受吧!
