尝试围绕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
这使我感到困惑,因为我没有做任何保存,只是选择。
我如何让它工作?我希望正确构建标准,当然不会发生错误。
答案 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=?