### 回答
要实现使用Criteria API结合Specification进行主表 `t_com` 和复合主键从表 `t_kbn` 的左外连接查询,并动态拼接查询条件 `com_name`,返回 `t_com` 的所有字段和 `t_kbn` 的 `kbn_name` 字段,可以按照以下步骤进行:
1. **定义实体类**:
- `TCom` 类,包含 `com_id`, `com_no`, `com_kbn1`, `com_kbn2`, `com_kbn3`, `com_kbn4`, `com_kbn5`, `com_name` 字段,并设置复合主键。
- `TKbn` 类,包含 `kbn`, `kbn_id`, `kbn_name`, `kbn_name2` 字段,并设置复合主键。
2. **创建 `Specification`**:
- 使用 `Specification` 来动态拼接查询条件,比如 `com_name`。
3. **使用 `CriteriaBuilder` 和 `CriteriaQuery`**:
- 创建 `CriteriaBuilder` 实例。
- 创建 `CriteriaQuery` 实例,指定查询的根(`Root<TCom>`)。
- 使用 `join` 方法进行左外连接,连接 `t_com` 和 `t_kbn` 表。
- 设置查询的选择列表,包含 `t_com` 的所有字段和 `t_kbn` 的 `kbn_name` 字段。
- 添加查询条件,包括动态拼接的条件。
4. **执行查询**:
- 使用 `EntityManager` 执行查询并获取结果。
以下是一个示例代码:
import javax.persistence.*;
import javax.persistence.criteria.*;
import java.util.*;
// 假设已经定义了 TCom 和 TKbn 实体类
public class DynamicQueryExample {
public List<Object[]> findComWithKbnName(EntityManager em, String comName) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<TCom> comRoot = cq.from(TCom.class);
// 左外连接 t_kbn 表,根据 com_kbn1, com_kbn2, ..., com_kbn5
List<Join<TCom, TKbn>> joins = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
String kbnFieldName = "com_kbn" + i;
Join<TCom, TKbn> join = comRoot.join("kbn" + i, JoinType.LEFT); // 假设在 TCom 中有对应的关联关系
joins.add(join);
cq.multiselect(
comRoot.get("com_id"),
comRoot.get("com_no"),
// ... 选择 t_com 的其他字段
comRoot.get("com_name"),
// 尝试从每个 join 中获取 kbn_name,这里需要处理多个可能的匹配情况
// 简单起见,这里只选择第一个 join 的 kbn_name 作为示例
// 实际应用中可能需要根据业务逻辑进行更复杂的处理
cb.coalesce(join.get("kbn_name"), cb.literal(""))
);
}
// 动态添加查询条件
Predicate namePredicate = comName != null ? cb.equal(comRoot.get("com_name"), comName) : cb.conjunction();
cq.where(namePredicate);
TypedQuery<Object[]> query = em.createQuery(cq);
return query.getResultList();
}
}
// 注意:
// 1. 上述代码中的关联关系(如 comRoot.join("kbn" + i, JoinType.LEFT))需要在实际实体类中定义。
// 2. 由于 t_com 的多个字段都与 t_kbn 有外键关系,这里的处理较为简化,实际业务中可能需要更复杂的逻辑来处理多个可能的匹配。
// 3. 使用 cb.coalesce 来处理可能的 null 值,确保查询结果中 kbn_name 字段不为 null。
**注意**:上述代码是一个简化的示例,用于说明如何使用Criteria API和Specification进行动态查询。在实际应用中,需要根据具体的实体类定义和业务逻辑进行适当调整。特别是处理多个可能的匹配和关联关系时,可能需要更复杂的逻辑。
项目目录结构
代码文件
Application.java
JpaConfig.java
ComController.java
Com.java
Kbn.java
ComRepository.java
KbnRepository.java
ComService.java
ComSpecification.java
application.properties
ApplicationTests.java