1

试图围绕 Criteria API(哎哟)。我有 3 个类:Devices、Offices 和 SiteCodes。全部加入

设备.java

private Offices office;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "office_id")
public Offices getOffice() {
    return office;
}

public void setOffice(Offices office) {
    this.office = office;
}

办公室.java:

private List<SiteCodes> siteCodes;

@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "site_code_map", joinColumns = { 
    @JoinColumn(name = "office_id") }, inverseJoinColumns = { 
    @JoinColumn(name = "site_code_id") })
@OrderBy("siteCode ASC")
public List<SiteCodes> getSiteCodes() {
    return this.siteCodes;
}

public void setSiteCodes(List<SiteCodes> siteCodes) {
    this.siteCodes = siteCodes;
}

站点代码.java

private id;
private String siteCode;
<getters and setters>

我正在尝试使用站点代码查找 Devices.devId。sql 看起来像这样:

 SELECT d.dev_id
   FROM devices d, offices o, site_code_map s, site_codes ss
  WHERE d.office_id=o.office_id
    AND s.office_id=o.office_id
    AND s.site_code_id=ss.site_code_id
    AND ss.`site_code`='0S21'

我正在尝试使用连接,但不太了解如何操作。我得到以下编译:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Integer> cq = cb.createQuery(Integer.class);
Root<Devices> d = cq.from(Devices.class); 
Join<Devices, Offices> join1 = d.join(Devices_.office);
ListJoin<Offices,SiteCodes> join2 = join1.join(Offices_.siteCodes);

我不知道如何使用 join2 所以我使用了 join1 和这样的路径

ParameterExpression<SiteCodes> p = cb.parameter(SiteCodes.class, "sitecode");
Predicate pr = cb.isMember(p, join1.get(Offices_.siteCodes));
cq.where(pr);

最终

TypedQuery<Integer> tq = em.createQuery(cq);
<set parameter here to a SiteCode object>
List<Integer> idList = tq.getResultList();

它产生如下的sql。该子查询不属于 - 我希望它使用连接,并且无论如何它都会抛出 TransientObjectException ,即使我所做的只是选择:

select
    devices0_.dev_id as col_0_0_ 
from
    devices devices0_ 
inner join
    offices offices1_ 
        on devices0_.office_id=offices1_.office_id 
inner join
    site_code_map sitecodes2_ 
        on offices1_.office_id=sitecodes2_.office_id 
inner join
    site_codes sitecodes3_ 
        on sitecodes2_.site_code_id=sitecodes3_.site_code_id 
where
    ? in (
       select
            sitecodes4_.site_code_id 
       from
            site_code_map sitecodes4_ 
       where
            offices1_.office_id=sitecodes4_.office_id

无论如何它也会抛出这个错误(不包括整个堆栈跟踪,除非有人想看到它):

Caused by: org.hibernate.TransientObjectException: object references an 
unsaved transient instance - save the transient instance before 
flushing: dne.nmst.dac.model.SiteCodes

这让我很困惑,因为我没有做任何保存,只是选择。

我怎样才能让它工作?我希望正确构建标准,当然不会发生错误。

4

1 回答 1

0

我解决了这个问题。希望它可以帮助别人。仍然不知道为什么我得到了它的错误,但我发现了连接并且使查询正常工作

加入:

Root<Devices> d = cq.from(Devices.class); 
Join<Devices, Offices> join1 = d.join(Devices_.office);
ListJoin<Offices,SiteCodes> join2 = join1.join(Offices_.siteCodes);

参数表达式和谓词:

ParameterExpression<String> p = cb.parameter(String.class, "sitecode");
Predicate pr = cb.equal(join2.get(SiteCodes_.siteCode),p);

产生这样的SQL:

select
  devices0_.dev_i a col_0_0 
from
  devices devices0 
inner join
  office offices1 
      o devices0_.office_id=offices1_.office_i 
inner join
  site_code_map sitecodes2 
      o offices1_.office_id=sitecodes2_.office_i 
inner join
  site_code sitecodes3 
      o sitecodes2_.site_code_id=sitecodes3_.site_code_i 
where
  sitecodes3_.site_code=?
于 2013-06-13T14:03:01.260 回答