其实,对这种情况的回答比你想象的要简单。使用正确的工具来完成正确的工作很简单。 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