1. Overview
1.概述
In this tutorial, we’ll discuss how to use the JPA static metamodel classes while writing criteria queries in Hibernate.
在本教程中,我们将讨论如何在Hibernate中编写标准查询时使用JPA静态元模型类。
We’ll need a basic understanding of criteria query APIs in Hibernate, so please check out our tutorial on Criteria Queries for more information on this topic, if needed.
我们需要对Hibernate中的标准查询API有一个基本的了解,所以如果需要的话,请查看我们关于标准查询的教程,以获得更多关于这个主题的信息。
2. Why the JPA Metamodel?
2.为什么是JPA元模型?
Often, when we write a criteria query, we need to reference entity classes and their attributes.
通常,当我们写一个标准查询时,我们需要引用实体类和它们的属性。
Now, one of the ways of doing this is to provide the attributes’ names as strings. But, this has several downsides.
现在,这样做的方法之一是将属性的名称作为字符串提供。但是,这有几个弊端。
For one, we have to look up the names of entity attributes. And, in case a column name is changed later in the project lifecycle, we have to refactor each query where the name is being used.
首先,我们必须查找实体属性的名称。而且,万一在项目生命周期的后期改变了列名,我们必须重构每个使用该名称的查询。
The JPA Metamodel was introduced by the community to avoid these drawbacks and provide static access to the metadata of the managed entity classes.
JPA元模型是由社区引入的,以避免这些缺点并提供对受管实体类元数据的静态访问。
3. Entity Class
3.实体类
Let’s consider a scenario where we are building a Student Portal Management system for one of our clients, and a requirement comes up to provide search functionality on Students based on their graduation year.
让我们考虑这样一个场景:我们正在为我们的一个客户建立一个学生门户管理系统,并要求提供基于毕业年份的学生搜索功能。
First, let’s look at our Student class:
首先,让我们看看我们的Student类。
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "grad_year")
private int gradYear;
// standard getters and setters
}
4. Generating JPA Metamodel Classes
4.生成JPA元模型类
Next, we need to generate the metamodel classes, and for this purpose, we’ll use the metamodel generator tool provided by JBoss. JBoss is just one of the many tools available to generate the metamodel. Other suitable tools include EclipseLink, OpenJPA, and DataNucleus.
接下来,我们需要生成元模型类,为此,我们将使用JBoss提供的元模型生成工具。JBoss只是众多可用于生成元模型的工具之一。其他合适的工具包括EclipseLink,OpenJPA,和DataNucleus。
To use the JBoss tool, we need to add the latest dependency in our pom.xml file, and the tool will generate the metamodel classes once we trigger the maven build command:
要使用JBoss工具,我们需要在pom.xml文件中添加最新依赖项,一旦我们触发maven构建命令,该工具就会生成元模型类。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.3.7.Final</version>
</dependency>
Note, we need to add the target/generated-classes folder to the classpath of our IDE, as by default, the classes will be generated in this folder only.
注意,我们需要将target/generated-classes文件夹添加到我们IDE的classpath中,因为默认情况下,类将只在这个文件夹中生成。
5. Static JPA Metamodel Classes
5.静态JPA元模型类
Based on the JPA specification, a generated class will reside in the same package as the corresponding entity class and will have the same name with an added “_” (underscore) at the end. So, the metamodel class generated for the Student class will be Student_ and will look something like:
基于JPA规范,生成的类将与相应的实体类驻留在同一个包中,并且将具有相同的名称,在结尾处添加”_”(下划线)。因此,为Student类生成的元模型类将是Student_,看起来会是这样。
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Student.class)
public abstract class Student_ {
public static volatile SingularAttribute<Student, String> firstName;
public static volatile SingularAttribute<Student, String> lastName;
public static volatile SingularAttribute<Student, Integer> id;
public static volatile SingularAttribute<Student, Integer> gradYear;
public static final String FIRST_NAME = "firstName";
public static final String LAST_NAME = "lastName";
public static final String ID = "id";
public static final String GRAD_YEAR = "gradYear";
}
6. Using JPA Metamodel Classes
6.使用JPA元模型类
We can use the static metamodel classes in the same way we would use the String references to attributes. The criteria query API provides overloaded methods that accept String references as well as Attribute interface implementations.
我们可以以使用属性的String引用的方式来使用静态元模型类。标准查询API提供了接受String引用的重载方法,以及Attribute接口的实现。
Let’s look at the criteria query that will fetch all Students who graduated in 2015:
让我们看一下标准查询,它将获取所有在2015年毕业的Students。
//session set-up code
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Student> criteriaQuery = cb.createQuery(Student.class);
Root<Student> root = criteriaQuery.from(Student.class);
criteriaQuery.select(root).where(cb.equal(root.get(Student_.gradYear), 2015));
Query<Student> query = session.createQuery(criteriaQuery);
List<Student> results = query.getResultList();
Notice how we’ve used the Student_.gradYear reference instead of using the conventional grad_year column name.
注意我们是如何使用Student_.gradYear参考,而不是使用传统的grad_year列名。
7. Conclusion
7.结语
In this quick article, we learned how to use static metamodel classes and why they may be preferred over the traditional way of using String references as described earlier.
在这篇快速文章中,我们学习了如何使用静态元模型类,以及为什么它们可能比前面描述的使用String引用的传统方式更受欢迎。
The source code of this tutorial can be found over on Github.
本教程的源代码可以在Github上找到over。