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。
享受吧!