1

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

選択するだけで保存をしていなかったので、これは私を混乱させました。

これを機能させるにはどうすればよいですか?基準を適切に構築し、もちろんエラーが発生しないようにしたいと考えています。

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 に答える