JPQL在很多关系上留下了外连接

时间:2013-12-10 17:05:41

标签: jpa many-to-many eclipselink left-join 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(或bug)的限制?我正在使用PostgreSQL v9.2和EclipseLink v2.4.2

提供更多详细信息...我有3个SQL表:item,tag和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;
...

1 个答案:

答案 0 :(得分:5)

我不确定它是否是一个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