2013-01-08 110 views
6

我有3个表等:JPA查询过连接表

A        AB      B 
-------------     ------------    --------------- 
a1        a1,b1     b1 

AB是A和B之间

利用该一个转换表,我的类有这两个类中没有组合物彼此。但我想知道,使用JPQL查询,如果有任何记录存在于我的元素AB表中的A表中。数字或布尔值是我需要的。

因为AB是一个转换表,所以没有模型对象,我想知道是否可以在我的Repository对象中使用@Query来完成此操作。

+0

我不是没有实体对象肯定JPQL。为什么不是SQL? – vels4j

+0

Sql可以轻松实现,但我想在我的项目中保持一致性(仅使用JPA)。但当然,如果没有办法做到这一点,我会选择SQL – Neron

回答

3

我建议使用JPQL的Native query method intead(JPA也支持原生查询)。让我们假设表A是客户,表B是产品,AB是销售。以下是获取客户订购产品清单的查询。

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

更正:认为你的意思是使用本机查询(即SQL)RATHER THQL JPQL(你把“原生查询JPQL”,而JPQL是JPA自己的查询语言)。 – DataNucleus

+0

@DataNucleus谢谢。现在更新答案。 – vels4j

+0

工作。谢谢 – Neron

4

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

+0

看起来是这样。无论如何感谢 – Neron

1

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