2013-12-10 57 views
1

我想编写一个查询(使用JPQL)来获取所有的标签和频率的每个已经被所有的项目引用。该JPQL是:JPQL留下许多外部联接一对多的关系

SELECT t.id, t.name, SIZE(t.items) FROM Tag t GROUP BY t.id, t.name ORDER BY t.name ASC 

注意,一些标签不被任何项目引用,但我还是希望他们包括在结果(和期待SIZE(t.items)将为零)。

但是,执行此查询时,它只返回那些与它相关联的项目的标签,忽略不受任何项目引用标签。从JPA生成的SQL是:

SELECT t0.id as a1, t0.NAME AS a2, COUNT(t1.id) FROM tag t0, item_tag_map t2, item t1 WHERE ((t2.tag_id = t0.id) AND (t1.id = t2.item_id)) GROUP BY t0.id, t0.NAME ORDER BY t0.NAME ASC; 

它不执行LEFT OUTER JOIN,它是获得我想要的结果所必需的。如果我在SQL中编写这个,我会做类似

select t.id, t.name, count(map.item_id) from tag as t left join item_tag_map as map on map.tag_id = t.id group by t.id, t.name order by t.name ASC; 

有什么办法可以在JPQL中实现这个吗?我做错了什么,或者它是JPQL(或错误)的限制吗?我使用PostgreSQL V9.2和的EclipseLink V2.4.2

为了提供更多的细节......我有3个SQL表:项目,标签和item_tag_map。这里有相关的Java类的代码片段:

@Entity 
@Table(name="item") 
public class Item implements Serializable { 
    @Id 
    @Column(name="id", updatable=false) 
    private String id; 

    @ManyToMany(cascade=CascadeType.ALL) 
    @JoinTable(
     name = "item_tag_map", 
     joinColumns = { @JoinColumn(name = "item_id", referencedColumnName = "id", nullable=false) }, 
     inverseJoinColumns = { @JoinColumn(name = "tag_id", referencedColumnName = "id", nullable=false) }) 
    private List<Tag> tags; 
... 


@Entity 
@Table(name="tag") 
@NamedQueries({ 
    @NamedQuery(name="Tag.findAllStats", query="SELECT t.id, t.name, SIZE(t.items) FROM Tag t GROUP BY t.id, t.name ORDER BY t.name ASC"), 
}) 
public class Tag implements Serializable { 
    @Id 
    @Column(name="id", updatable=false) 
    private long id; 

    private String name; 

    @ManyToMany(mappedBy="tags", fetch=FetchType.LAZY) 
    private List<Item> items; 
... 

回答

4

我不知道,如果它是一个EclipseLink的错误或不(它看起来是一个对我来说,虽然),但你可能可以使用下面的查询解决问题(未经测试):

select t.id, t.name, count(i.id) from Tag t 
left join t.items i 
group by t.id, t.name 
order by t.name asc 
+0

谢谢!我尝试了这一点,它的工作原理。从JPQL生成的SQL并不是最大的,但现在就足够了。 –