其實,對這種情況的回答比你想象的要簡單。使用正確的工具來完成正確的工作很簡單。 JPA並不是爲執行復雜的SQL查詢而設計的,這就是SQL的用途!所以你需要一種方法讓JPA訪問生產級的SQL查詢;
em.createNativeQuery
所以在你的情況下,你想要做的就是訪問AB表只尋找id字段。檢索完查詢後,請帶上您的id字段並使用id字段查找Java對象。這是第二次搜索真實,但SQL標準微不足道。
我們假設您正在尋找一個基於B對象引用次數的A對象。假設您想要一個半複雜的(但是典型的)SQL查詢來根據B對象的數量並按降序對A型對象進行分組。這將是一個典型的熱門查詢,您可能需要按照項目要求來實施。
你的原生SQL查詢是這樣:
select a_id as id from AB group by a_id order by count(*) desc;
現在,你想要做的是告訴JPA期望的形式是JPA可以接受ID列表翻盤。您需要組合一個額外的JPA實體。永遠不會以JPA的正常方式使用它。但JPA需要一種方法將查詢的對象返回給您。您將爲此搜索查詢組合一個實體,
@Entity
public class IdSearch {
@Id
@Column
Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
現在你實現一小段代碼將兩種技術結合在一起;
@SuppressWarnings("unchecked")
public List<IdSearch> findMostPopularA() {
return em.createNativeQuery("select a_id as id from AB group by a_id
order by count(*) desc", IdSearch.class).getResultList();
}
在那裏,這就是爲了讓JPA成功完成查詢所需要做的所有事情。爲了獲得你的A對象,你可以簡單地使用傳統的JPA方法交叉引用你的A列表,
List<IdSearch> list = producer.getMostPopularA();
Iterator<IdSearch> it = list.iterator();
while (it.hasNext()) {
IdSearch a = it.next();
A object = em.find(A.class,a.getId());
// your in business!
儘管如此,上述的一點細化可以讓事情更簡單一些,因爲SQL設計結構有許多功能。一個稍微複雜的SQL查詢將更直接的JPA接口到您的實際數據;
@SuppressWarnings("unchecked")
public List<A> findMostPopularA() {
return em.createNativeQuery("select * from A, AB
where A.id = AB.a_id
group by a_id
order by count(*) desc", A.class).getResultList();
}
這消除了需要一個國際IdSearch表!
List<A> list = producer.getMostPopularA();
Iterator<A> it = list.iterator();
while (it.hasNext()) {
A a = it.next();
// your in business!
TOT肉眼是奇妙簡化的方式JPA使您可以在JPA界面中使用複雜的SQL結構的可能不是很清楚什麼。想象一下,如果你的SQL如下所示;
SELECT array_agg(players), player_teams
FROM (
SELECT DISTINCT t1.t1player AS players, t1.player_teams
FROM (
SELECT
p.playerid AS t1id,
concat(p.playerid,':', p.playername, ' ') AS t1player,
array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
FROM player p
LEFT JOIN plays pl ON p.playerid = pl.playerid
GROUP BY p.playerid, p.playername
) t1
INNER JOIN (
SELECT
p.playerid AS t2id,
array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
FROM player p
LEFT JOIN plays pl ON p.playerid = pl.playerid
GROUP BY p.playerid, p.playername
) t2 ON t1.player_teams=t2.player_teams AND t1.t1id <> t2.t2id
) innerQuery
GROUP BY player_teams
的一點是,與createNativeQuery接口,仍然可以檢索精確的數據,您正在尋找直入,以方便的Java所需的對象。
@SuppressWarnings("unchecked")
public List<A> findMostPopularA() {
return em.createNativeQuery("SELECT array_agg(players), player_teams
FROM (
SELECT DISTINCT t1.t1player AS players, t1.player_teams
FROM (
SELECT
p.playerid AS t1id,
concat(p.playerid,':', p.playername, ' ') AS t1player,
array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
FROM player p
LEFT JOIN plays pl ON p.playerid = pl.playerid
GROUP BY p.playerid, p.playername
) t1
INNER JOIN (
SELECT
p.playerid AS t2id,
array_agg(pl.teamid ORDER BY pl.teamid) AS player_teams
FROM player p
LEFT JOIN plays pl ON p.playerid = pl.playerid
GROUP BY p.playerid, p.playername
) t2 ON t1.player_teams=t2.player_teams AND t1.t1id <> t2.t2id
) innerQuery
GROUP BY player_teams
", A.class).getResultList();
}
乾杯,
佩裏
[email protected]
我不是沒有實體對象肯定JPQL。爲什麼不是SQL? – vels4j
Sql可以輕鬆實現,但我想在我的項目中保持一致性(僅使用JPA)。但當然,如果沒有辦法做到這一點,我會選擇SQL – Neron