Hibernate 静态元模型简介
1. 概述
在本教程中,我们将讨论在 Hibernate 中编写条件查询时如何使用 JPA 静态元模型类。
我们需要对 Hibernate 中的条件查询 API 有基本的了解,因此如果需要,请查看我们的条件查询教程 以获取有关此主题的更多信息。
2. 为什么使用 JPA 元模型?
通常,当我们编写条件查询时,我们需要引用实体类及其属性。
现在,其中一种方法是将属性名称作为字符串提供。但是,这有几个缺点。
首先,我们必须查找实体属性的名称。而且,如果列名在项目生命周期的后期发生更改,我们必须重构使用该名称的每个查询。
社区引入了JPA 元模型 来避免这些缺点并提供对托管实体类的元数据的静态访问。
3. 实体类
让我们考虑一个场景,我们正在为我们的一个客户构建一个学生门户管理系统,并且出现了根据Student毕业年份提供搜索功能的要求。
首先,让我们看看我们的 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. 生成 JPA 元模型类
接下来,我们需要生成元模型类,为此,我们将使用JBoss 提供的元模型生成器工具。JBoss 只是众多可用于生成元模型的工具之一。其他合适的工具包括 EclipseLink 、 OpenJPA 和 DataNucleus 。
要使用 JBoss 工具,我们需要在我们的 pom.xml文件中添加最新的依赖项 ,一旦我们触发 maven build 命令,该工具就会生成元模型类:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.3.7.Final</version>
</dependency>
请注意,我们需要将target/generated-classes文件夹添加 到 IDE 的类路径中,因为默认情况下,类将仅在此文件夹中生成。
5. 静态 JPA 元模型类
根据 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. 使用 JPA 元模型类
**我们可以像使用字符串引用属性一样使用静态元模型类。**条件查询 API 提供了重载方法,这些方法接受String引用以及 Attribute接口实现。
让我们看一下将获取 2015 年毕业的所有Student的条件查询:
//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();
请注意我们如何使用 Student_.gradYear引用而不是使用常规的grad_year列名称。