标准 JPA 2 与 3 个表格

Posted

技术标签:

【中文标题】标准 JPA 2 与 3 个表格【英文标题】:Criteria JPA 2 with 3 tables 【发布时间】:2013-06-13 19:54:15 【问题描述】:

我正在尝试创建一个标准以从 3 个表(关联、更新和详细信息)中检索一些对象。 Detail 引用了 Associate 和 Update,Update 引用了 Details 列表。我的目标是检索一个更新列表,在给定关联 ID 的情况下,该列表在指定字段中至少有一个具有空值的详细信息。在 JPQL 中很容易做到,但客户说这必须用标准编码。

我的 JPQL 是:

public List<Update> getUpdates(long associateId) 
    TypedQuery<Update> query = em.createQuery("select distinct u from Update u, Detail dt, Associate a "
        + "where dt.update = u and dt.associate = a and a.associateId = :id and "
        + "dt.ack_date is null", Update.class);
    query.setParameter("id", associateId);
    return query.getResultList();

我尝试了以下方法,但它只是返回了数据库中的所有更新:

public List<Update> getUpdates(long associateId) 
    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Update> query = builder.createQuery(Update.class);

    Root<Update> fromUpdates = query.from(Update.class);
    Root<Associate> fromAssociate = query.from(Associate.class);
    Root<Detail> fromDetail = query.from(Detail.class);

    Join<Detail, Associate> associateJoin = fromDetail.join("associate");
    Join<Detail, Update> updateJoin = fromDetail.join("update");

    TypedQuery<Update> typedQuery = em.createQuery(query

            .select(fromUpdates)
            .where(builder.and(
                    builder.equal(fromAssociate.get("associateId"), associateId),
                    builder.equal(fromDetail.get("associate"), associateJoin),
                    builder.equal(fromDetail.get("update"), updateJoin),
                    builder.isNull(fromDetail.get("ack_date"))
            ))

            .orderBy(builder.asc(fromUpdates.get("updateId")))
            .distinct(true)
    );

    return typedQuery.getResultList();

谁能帮帮我?我搜索但找不到任何包含 3 个实体的示例。

【问题讨论】:

【参考方案1】:

每个连接都将您从左侧类型参数带到右侧。因此,我的代码(第二行)的details 连接从fromUpdates 开始,即Path&lt;Update&gt;,并在幕后创建了Path&lt;Detail&gt;。由此,您可以构建其他连接。试试这个(代码未测试):

Root<Update> fromUpdates = query.from(Update.class);
Join<Update, Detail> details = fromUpdates.join("details");
Join<Detail, Associate> associate = details.join("associate");
List<Predicate> conditions = new ArrayList();
conditions.add(builder.equal(associate.get("associateId"), associateId));
conditions.add(builder.isNull(details.get("ack_date")));

TypedQuery<Update> typedQuery = em.createQuery(query
        .select(fromUpdates)
        .where(conditions.toArray(new Predicate[] ))
        .orderBy(builder.asc(fromUpdates.get("updateId")))
        .distinct(true)
);

【讨论】:

工作就像一个魅力!这些标准加入让我发疯了,但这有很大帮助!谢谢 perissf :)【参考方案2】:

涉及三个表。

CriteriaBuilder builder = theEntityManager.getCriteriaBuilder(); CriteriaQuery query1 = builder.createQuery(BasicMemberInfo.class);

    Root<Table1> table1 = query1.from(Table1.class); 
    Root<Table2> table2 = query1.from(Table2.class);
    Root<Table3> table3 = query1.from(Table3.class);

   List<Predicate> conditions = new ArrayList();
    conditions.add(builder.equal(table3.get("Table1").get("memberId"), table1.get("memberId")));
    conditions.add(builder.equal(table2.get("tableid").get("memberId"), table1.get("memberId")));
    conditions.add(builder.equal(table2.get("indicator"), 'Y'));
    conditions.add(builder.equal(table3.get("StatusCd"), "YES"));

    TypedQuery<BasicCustInfo> typedQuery = theEntityManager.createQuery(
            query1.multiselect(table1.get("memberId"), table2.get("AcctId"))
            .where(conditions.toArray(new Predicate[] ))
    );

    List<BasicMemberInfo> custList = typedQuery.getResultList();

公共类 BasicMemberInfo

String memberId;
String AcctId;

public BasicCustInfo() 
    // TODO Auto-generated constructor stub


public BasicMemberInfo( BigDecimal memberId,String AcctId ) 
    this.memberId = memberId;
    this.AcctId = AcctId;


public BigDecimal getmemberId() 
    return memberId;

public void setmemberId(BigDecimal memberId) 
    memberId = memberId;

public String getAcctId() 
    return AcctId;

public void setAcctId(String AcctId) 
    AcctId = AcctId;

【讨论】:

是否使用了多个条件,例如带有 WHERE x=y AND a=b AND c=d .... 的 sql 语句。还是我必须使用“and(Predicate)”方法来确定? 这就像一条带 Where 子句的 SQL 语句。 conditions.add(builder.equal(table3.get("Table1").get("memberId"), table1.get("memberId"))); 表示Table3类有成员变量Table1?如果它有@OneToMany 关系怎么办。并且有 List,我们该怎么做呢?【参考方案3】:

用三个以上的表检查这个测试。也使用静态元模型而不是使用直接属性名称。

    @Test
@Rollback(false)
@Transactional
public void   
fetch() 
    CriteriaBuilder cb = 
entityManager.getCriteriaBuilder();
    CriteriaQuery<Instructor> cq = 
cb.createQuery(Instructor.class);
    Root<Instructor> root = 
cq.from(Instructor.class);
    root.join(Instructor_.idProof);
    root.join(Instructor_.vehicles);
    Join<Instructor, Student> insStuJoin = 
root.join(Instructor_.students);
    insStuJoin.join(Student_.instructors);
    Join<Student, Vehicle> stuVehcileJoin.   
= insStuJoin.join(Student_.vehicles);
    Join<Vehicle, Document> 
vehicleDocumentJoin = 
stuVehcileJoin.join(Vehicle_.documents);

DataPrinters.
listDataPrinter.accept.   
(queryExecutor.fetchListForCriteriaQuery
      (cq.select(root).where
(cb.greaterThan(root.get(Instructor_.id), 2),                        
           cb.in(vehicleDocumentJoin.get
                          (Document_.name)).value("1")
.value("2").value("3")));

【讨论】:

以上是关于标准 JPA 2 与 3 个表格的主要内容,如果未能解决你的问题,请参考以下文章

带有两个子查询/连接的 JPA 标准选择

多对多关系的jpa标准

JPA命名查询与标准API?

标准 JPA 2,Hibernate - 多重连接

单表继承(休眠)的 JPA 2 标准查询

JPA 2.0、标准 API、子查询、表达式中