2013-06-12 24 views
1

試圖圍繞Criteria API(ouch)包裹我的頭。我有3個類:設備,辦公室和SiteCodes。所有加入爲什麼org.hibernate.TransientObjectException在加入/選擇?

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 

這迷惑了我,因爲我沒有做任何儲蓄,只是選擇。

我如何得到這個工作?我希望正確構建標準,當然不會發生錯誤。

回答

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=?