高级查询中的实体图使用指南
立即解锁
发布时间: 2025-08-19 02:00:34 阅读量: 1 订阅数: 7 


Java Persistence API实战指南
### 高级查询中的实体图使用指南
#### 1. 实体图基础与简化
在处理实体图时,我们常常会发现一些注解示例显得过于复杂。实际上,很多情况下可以利用默认获取图规则来简化这些定义。例如,以下是一个部门实体类的定义:
```java
public class Department {
@Id private int id;
private String name;
@OneToMany(mappedBy="department")
@MapKey(name="name")
private Map<EmployeeName, Employee> employees;
// ...
}
```
现在我们已经了解了实体图的相关规则,不妨回顾之前定义的命名实体图,尝试运用默认获取图规则对其进行简化。
#### 2. 实体图 API
实体图 API 为我们在代码中动态创建、修改和添加实体图提供了便利。通过该 API,我们能够根据程序参数、用户输入甚至静态数据来生成获取计划。下面将详细介绍 API 中的类和主要方法,并通过示例展示如何创建与之前注解部分等效的动态实体图。
##### 2.1 创建新的实体图
创建新实体图的第一步是使用 `EntityManager` 的 `createEntityGraph()` 工厂方法。该方法以根实体类作为参数,并返回一个类型为该实体类的新 `EntityGraph` 实例。示例代码如下:
```java
EntityGraph<Address> graph = em.createEntityGraph(Address.class);
```
##### 2.2 添加属性节点
接下来,我们需要向实体图中添加属性节点。可以使用可变参数的 `addAttributeNodes()` 方法来添加那些不需要关联子图的属性。示例如下:
```java
graph.addAttributeNodes("street","city", "state", "zip");
```
此操作会为每个指定的属性参数创建一个 `AttributeNode` 对象,并将其添加到实体图中。不过,目前并没有与 `@NamedEntityGraph` 注解中的 `includeAllAttributes` 元素等效的方法。
除了使用字符串类型的属性名,还有强类型的方法可供选择。这些强类型版本使用元模型,因此需要确保为领域模型生成了元模型。以下是强类型 `addAttributeNodes()` 方法的调用示例:
```java
graph.addAttributeNodes(Address_.street, Address_.city,
Address_.state, Address_.zip);
```
##### 2.3 添加子图
当需要为某个属性添加子图时,不应使用 `addAttributeNodes()` 方法,而应使用 `addSubgraph()` 方法的不同变体。每个 `addSubgraph()` 方法会先为传入的属性创建一个 `AttributeNode` 实例,接着创建一个 `Subgraph` 实例,然后将子图与属性节点关联起来,最后返回 `Subgraph` 实例。以下是一个带有子图的动态实体图示例:
```java
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
graph.addAttributeNodes("name","salary", "address");
Subgraph<Phone> phone = graph.addSubgraph("phones");
phone.addAttributeNodes("number", "type");
Subgraph<Department> dept = graph.addSubgraph("department");
dept.addAttributeNodes("name");
```
从上述示例可以看出,基于 API 的实体图比基于注解的实体图更加简洁易读。
#### 3. 不同场景下的实体图创建
##### 3.1 包含多个类型定义的实体图
在某些情况下,实体图可能需要包含根实体类的第二个定义,或者一个子图引用另一个子图。以下是一个示例:
```java
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
graph.addAttributeNodes("name","salary", "address");
Subgraph<Phone> phone = graph.addSubgraph("phones");
phone.addAttributeNodes("number", "type");
Subgraph<Employee> namedEmp = phone.addSubgraph("employee");
namedEmp.addAttributeNodes("name");
Subgraph<Department> dept = graph.addSubgraph("department");
dept.addAttributeNodes("name");
Subgraph<Employee> mgrNamedEmp = graph.addSubgraph("manager");
mgrNamedEmp.addAttributeNodes("name");
```
需要注意的是,API 在这种情况下存在一定的局限性,因为它不允许在同一个实体图中共享子图。所以,我们需要构建两个相同的命名员工子图。
##### 3.2 带有继承关系的实体图
当相关类存在类层次结构时,每次调用 `addSubgraph()` 方法时可以传入类作为参数,以区分不同的子类。以下是一个带有继承关系的动态实体图示例:
```java
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
graph.addAttributeNodes("name","salary", "address");
Subgraph<Project> project = graph.addSubgraph("projects", Project.class);
project.addAttributeNodes("name");
Subgraph<QualityProject> qaProject = graph.addSubgraph("projects", QualityProject.class);
qaProject.addAttributeNodes("qaRating");
```
当根实体类存在继承关系时,应使用 `addSubclassSubgraph()` 方法。以下是一个示例:
```java
EntityGraph<Employee> graph = em.createEntityGraph(Employee.class);
graph.addAttributeNodes("name","address");
graph.addSubgraph("department").addAttributeNodes("name");
graph.addSubclassSubgraph(ContractEmployee.class).addAttributeNodes("hourlyRate");
```
##### 3.3 带有映射键子图的实体图
最后,我们来看一个映射示例。以下是将其转换为基于 API 的版本:
```java
EntityGraph<Department> graph = em.createEntityGraph(Department.class);
graph.addAttributeNodes("name");
graph.addSubgraph("employees").addAttributeNodes("salary");
graph.addKeySubgraph("employees").addAttributeNodes("firstName", "lastName");
```
在上述示例中,`addKeySubgraph()` 方法可以在根实体图节点上调用,同样也存在于 `Subgraph` 中,因此可以在任何出现映射的级别添加键子图。
#### 4. 实体图的管理
前面我们已经学习了如何创建命名和动态实体图,接下来将探讨如何对它们进行管理。实体图的管理主要包括访问、保存、修改以及基于现有实体图创建新的实体图。
##### 4.1 访问命名实体图
动态实体图的访问较为简单,因为在创建过程中我们将其存储在同一个变量中。而对于命名实体图,需要通过实体管理器来访问。可以通过将实体图的名称传递给 `getEntityGraph()` 方法来实现,该方法将返回一个 `EntityGraph` 对象。示例如下:
```java
EntityGraph<?> empGraph2 = em.getEntityGraph("Employee.graph2");
```
需要注意的是,由于实体管理器不知道实体图的具体类型,因此类型参数使用了通配符。
如果在一个类上定义了多个实体图,并且需要对它们进行遍历,可以使用基于类的访问器方法。以下代码展示了如何查看每个员工实体图的根实体类的属性名称:
```java
List<En
```
0
0
复制全文
相关推荐









