Criteria API (痛い) に頭を悩ませようとしています。デバイス、オフィス、サイトコードの 3 つのクラスがあります。全員参加
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
選択するだけで保存をしていなかったので、これは私を混乱させました。
これを機能させるにはどうすればよいですか?基準を適切に構築し、もちろんエラーが発生しないようにしたいと考えています。