我試圖使用Criteria Query API + RAD/Dali自動生成的用於OpenJPA 2.1的靜態規範元模型複製以下工作查詢在WebSphere v8.0.0.5 1,2-快照:JPA2 - 如何按OpenJPA中的嵌入式組合主鍵中的字段排序
`SELECT *
FROM CENTER c
INNER JOIN STATE s ON s.ID = c.STATE_ID
INNER JOIN HOURS_OF_OPERATION h ON h.CENTER_ID = c.ID
WHERE c.CITY = '<city_name_here>'
ORDER BY h.WEEKDAY_NUMBER;`
我有形成此查詢的核心四個實體:
- Center.java
- State.java
- 侯rsOfOperation.java
- HoursOfOperationPK.java
有每個國家的許多中心。每個中心有許多HoursOfOperations。我需要返回包含中心信息,狀態縮寫以及中心運行小時數的結果集,以星期一至星期日的星期幾1-7表示。
這裏是我的方法:
public Center getCenterInfo(String centerCityName) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Center> cq = cb.createQuery(Center.class);
Metamodel m = em.getMetamodel();
EntityType<Center> _center = m.entity(Center.class);
EntityType<State> _state = m.entity(State.class);
Root<Center> center = cq.from(_center);
Join<Center, State> state = center.join(Center_.state);
Join<Center, HoursOfOperation> hop = center.join(Center_.hoursOfOperations);
cq.select(center).distinct(true);
Predicate predicate = cb.equal(center.get(Center_.city), centerCityName);
cq.where(predicate);
//cq.orderBy(cb.asc(hop.get(HoursOfOperation_.id)));<---Can't access PK field here
center.fetch(Center_.state);
center.fetch(Center_.hoursOfOperations);
TypedQuery<Center> query = em.createQuery(cq);
Center centerInfo = query.getSingleResult();
return centerInfo;
}
我註釋掉了我卡就行了。我想我必須調用一些方法來實例化某種HoursOfOperationPK實例,就像我使用Join<Center, HoursOfOperation> hop
一樣。我認爲這樣做可以讓我使用類似cq.orderBy(cb.asc(hopPk.get(HoursOfOperationPK_.weekdayNumber)));
的東西我該如何做到這一點?其次,如果我不使用cq.select(center).distinct(true);
,我會取回49條記錄而不是7條記錄。這是爲什麼?將記錄倒數至7的唯一方法是附加到選擇的獨特方法。我理解DISTINCT在SQL中的作用,但是我的ANSI風格的SQL語法只返回7條記錄。
OpenJPA日誌輸出表明OrderBy應用於HoursOfOperation.centerId。
這裏的HoursOfOperation的相關部分和HoursOfOperationPK實體:
@Entity
@Table(name="HOURS_OF_OPERATION")
public class HoursOfOperation implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private HoursOfOperationPK id;
public HoursOfOperationPK getId() {
return this.id;
}
public void setId(HoursOfOperationPK id) {
this.id = id;
}
}
@Embeddable
public class HoursOfOperationPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
@Column(name="CENTER_ID", unique=true, nullable=false)
private long centerId;
@Column(name="WEEKDAY_NUMBER", unique=true, nullable=false)
private long weekdayNumber;
public HoursOfOperationPK() {
}
public long getCenterId() {
return this.centerId;
}
public void setCenterId(long centerId) {
this.centerId = centerId;
}
public long getWeekdayNumber() {
return this.weekdayNumber;
}
public void setWeekdayNumber(long weekdayNumber) {
this.weekdayNumber = weekdayNumber;
}
}
編輯 @perissf我是能夠產生使用期望的結果SANS明確的順序由ASC(一種似乎隱含發生由於weekdayNumber是運營小時表的複合主鍵的一部分,我寧願有明確的排序,因爲它可以幫助我進行其他查詢,我可能不那麼幸運):
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Center> cq = cb.createQuery(Center.class);
Metamodel m = em.getMetamodel();
EntityType<Center> _center = m.entity(Center.class);
Root<Center> center = cq.from(_center);
Expression<List<HoursOfOperation>> hop = center.get(Center_.hoursOfOperations);
cq.select(center);
Predicate predicate = cb.equal(center.get(Center_.city), centerCityName);
cq.where(predicate);
center.fetch(Center_.state);
center.fetch(Center_.hoursOfOperations);
TypedQuery<Center> query = em.createQuery(cq);
Center centerInfo = query.getSingleResult();
但是,我能夠使用以下方式生成所需的SQL,但唯一的問題是中心的hoursOfOperation未設置(由於延遲加載。 A center.Fetch(Center_.hoursOfOperation)
創建重複記錄。任何人都有解決方案?):
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Center> cq = cb.createQuery(Center.class);
Metamodel m = em.getMetamodel();
EntityType<Center> _center = m.entity(Center.class);
Root<Center> center = cq.from(_center);
EntityType<HoursOfOperation> _hoo = m.entity(HoursOfOperation.class);
Root<HoursOfOperation> hoo = cq.from(_hoo);
cq.select(center).distinct(true);
Predicate predicate = cb.and(cb.equal(center.get(Center_.city), centerCityName),
cb.equal(center, hoo.get(HoursOfOperation_.center)));
cq.where(predicate);
cq.orderBy(cb.asc(hoo.get(HoursOfOperation_.id).get(HoursOfOperationPK_.weekdayNumber)));
center.fetch(Center_.state);
TypedQuery<Center> query = em.createQuery(cq);
Center centerInfo = query.getSingleResult();
我想出了WAS v8的trace.log文件的位置。我可以看到這些查詢。至少在正確的方向上取得了一些進展。 –
O.K.取得了更多進展。我可以通過Path對象導航到HoursOfOperationPK: 'Path hopPk = hop.get(HoursOfOperation_.id); cq.orderBy(cb.asc(hopPk.get(HoursOfOperationPK_.weekdayNumber)));' 這會在生成的SQL中按兩個不同的HoursOfOperation別名的weekdayNumber和centerId字段進行排序。如果其中一個HoursOfOperation別名僅用於按星期幾編號進行排序,並且centerId排序被刪除,那麼更正問題的方法是什麼。我怎樣才能做到這一點? –