为什么在join / select期间有org.hibernate.TransientObjectException?

时间:2013-06-12 18:23:30

标签: criteria-api

尝试围绕Criteria API(ouch)。我有3个类:设备,办公室和SiteCodes。全部加入

Devices.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;
}

Offices.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;
}

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

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

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

这使我感到困惑,因为我没有做任何保存,只是选择。

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

1 个答案:

答案 0 :(得分: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=?