我有3个表,如:
A AB B
------------- ------------ ---------------
a1 a1,b1 b1
AB是A和B之间的转换表
有了这个,我的类在这两个类中没有相互组合。但我想知道,使用JPQL查询,如果我的元素存在于AB表中的A表中的任何记录。我需要的只是数字或布尔值。
因为AB是一个转换表,所以没有模型对象,我想知道我是否可以在我的Repository对象中使用@Query执行此操作。
答案 0 :(得分:5)
必须在要在JPQL中查询的实体中建模AB表。所以你必须将其建模为 您自己的实体类或A和/或B实体中的关联。
答案 1 :(得分:4)
我建议使用JP Native query method intead(JPA也支持Native查询)。我们假设表A是Customer,表B是Product,AB是Sale。以下是获取客户订购产品列表的查询。
entityManager.createNativeQuery("SELECT PRODUCT_ID FROM
SALE WHERE CUSTOMER_ID = 'C_123'");
答案 2 :(得分:2)
实际上,这种情况的答案比你想象的要简单。使用正确的工具来完成正确的工作很简单。 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();
}
在那里,您需要做的就是让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();
}
这消除了对interm IdSearch表的需求!
List<A> list = producer.getMostPopularA();
Iterator<A> it = list.iterator();
while ( it.hasNext() ) {
A a = it.next();
// your in business!
肉眼可能不太清楚的是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();
}
干杯,
佩里
info@unifiedobjects.net