连接表上的JPA查询

连接表上的JPA查询,jpa,jpql,Jpa,Jpql,我有3张桌子,比如: A AB B ------------- ------------ --------------- a1 a1,b1 b1 AB是a和B之间的转换表 有了这个,我的班级就没有了这两个班级的作文了。但我想知道,对于JP

我有3张桌子,比如:

A                              AB                        B
-------------                  ------------              ---------------
a1                              a1,b1                    b1
AB是a和B之间的转换表

有了这个,我的班级就没有了这两个班级的作文了。但我想知道,对于JPQL查询,AB table中的表中是否存在我的元素的任何记录。我只需要一个数字或布尔值


因为AB是一个转换表,所以它没有模型对象,我想知道我是否可以在我的存储库对象中使用@Query来实现这一点。

AB表必须在JPQL中要查询的实体中建模。因此,您必须将其建模为 A和/或B实体中自己的实体类或关联。

我建议使用JPQL的intead(JPA也支持本机查询)。假设表A是客户,表B是产品,表B是销售。下面是获取客户订购的产品列表的查询

entityManager.createNativeQuery("SELECT PRODUCT_ID FROM 
                                     SALE WHERE CUSTOMER_ID = 'C_123'");

事实上,这种情况的答案比你想象的要简单。这是一个简单的问题,使用正确的工具进行正确的工作。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希望id列表以JPA可以接受的形式重新出现。您需要组建一个额外的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();
    }
@SuppressWarnings(“未选中”)
公共列表findMostPopularA(){
返回em.createNativeQuery(“按\u id从AB组中选择一个\u id作为id
按计数排序(*)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!
List List=producer.getMostPopularA();
Iterator it=list.Iterator();
while(it.hasNext()){
IdSearch a=it.next();
A object=em.find(A.class,A.getId());
//你在做生意!
尽管如此,考虑到SQL设计结构的许多功能,对上述内容进行进一步的细化可以进一步简化事情

    @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();
    }
@SuppressWarnings(“未选中”)
公共列表findMostPopularA(){
返回em.createNativeQuery(“从A、AB中选择*
其中A.id=AB.A_id
按a_id分组
按计数排序(*)desc“,A.class).getResultList();
}
这样就不需要interm IdSearch表了

List<A> list = producer.getMostPopularA();
Iterator<A> it = list.iterator();
while ( it.hasNext() ) {
    A a = it.next();
    // your in business!
List List=producer.getMostPopularA();
Iterator it=list.Iterator();
while(it.hasNext()){
A=it.next();
//你在做生意!
也许肉眼看不清楚的是,JPA以惊人的简化方式允许您在JPA界面内使用复杂的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
选择阵型、球员、球队
从(
选择不同的t1.t1player作为玩家,t1.player\U团队
从(
挑选
p、 playerid作为t1id,
康卡特(p.playerid,“:”,p.playername,“)作为球员,
数组\u agg(pl.teamid按pl.teamid排序)作为玩家\u团队
来自玩家p
左连接在p.playerid=pl.playerid上播放pl
按p.playerid、p.playername分组
)t1
内连接(
挑选
p、 playerid作为t2id,
数组\u agg(pl.teamid按pl.teamid排序)作为玩家\u团队
来自玩家p
左连接在p.playerid=pl.playerid上播放pl
按p.playerid、p.playername分组
)t1上的t2。玩家团队=t2.player团队和t1.t1id t2.t2id
)内部查询
按球员分组
关键是,使用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();
    }
@SuppressWarnings(“未选中”)
公共列表findMostPopularA(){
返回em.createNativeQuery(“选择数组\玩家、玩家\团队
从(
选择不同的t1.t1player作为玩家,t1.player\U团队
从(
挑选
p、 playerid作为t1id,
康卡特(p.playerid,“:”,p.playername,“)作为球员,
数组\u agg(pl.teamid按pl.teamid排序)作为玩家\u团队
来自玩家p
左连接在p.playerid=pl.playerid上播放pl
按p.playerid、p.playername分组
)t1
内连接(
挑选
p、 playerid作为t2id,
数组\u agg(pl.teamid按pl.teamid排序)作为玩家\u团队
来自玩家p
左连接在p.playerid=pl.playerid上播放pl
按p.playerid、p.playername分组
)t1上的t2。玩家团队=t2.player团队和t1.t1id t2.t2id
)内部查询
按球员分组
,A.class.getResultList();
}
干杯

佩尔