You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从关联的ManyToMany表中查询指定分类的Item列表?

问题背景

存在两个通过@ManyToMany关联的JPA实体:

Category实体

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Category {
    @Id
    @GeneratedValue(generator = Constants.ID_GENERATOR)
    protected Long id;

    protected String code;

    @ManyToMany(CascadeType.PERSIST)
    @JoinTable(
        name = "CATEGORY_ITEM",
        joinColumns = @JoinColumn(name = "CATEGORY_ID"),
        inverseJoinColumns = @JoinColumn(name = "ITEM_ID")
    )
    protected Set<Item> items = new HashSet<Item>();

    @Override
    public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
       Category category = (Category) o;
      return Objects.equals(code, category.code);
    }
 
    @Override
    public int hashCode() {
       return Objects.hash(code);
    }
}

Item实体

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Item {
    @Id
    @GeneratedValue(generator = Constants.ID_GENERATOR)
    protected Long id;

    protected String code;

    @ManyToMany(mappedBy = "items")
    protected Set<Category> categories = new HashSet<Category>();

    @Override
    public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
       Item item = (Item) o;
      return Objects.equals(code, item.code);
    }
 
    @Override
    public int hashCode() {
       return Objects.hash(code);
    }
}

尝试通过JPQL获取指定code的分类下所有Item时,所有查询均返回空列表,但直接通过ID查询Category实体后,能正常获取关联的Item集合:

Category category = categoryRepository.findById(1L).orElseThrow();
assertEquals(category.getItems().size(), 2);
问题根源

所有JPQL查询返回空的原因是:查询语句中使用了西里尔字母с(俄语小写c)代替了英文小写字母c,例如第一个查询中的join с.items i,JPA无法识别这个错误的别名,导致查询逻辑失效。

正确的查询写法

以下是几种可行的正确JPQL查询:

1. CategoryRepository中的关联查询

@Query("select i from Category c join c.items i where c.code = :code")
List<Item> findItemsWithCode(@Param("code") String code);

如果需要避免重复(当Item属于多个分类时),可以添加distinct:

@Query("select distinct i from Category c join c.items i where c.code = :code")
List<Item> findItemsWithCode(@Param("code") String code);

2. CategoryRepository中直接查询关联集合

@Query("select c.items from Category c where c.code = :code")
List<Item> findItemsWithCode(@Param("code") String code);

3. ItemRepository中的反向关联查询

@Query("select i from Item i join i.categories c where c.code = :code")
List<Item> findItemsWithCode(@Param("code") String code);

内容的提问来源于stack exchange,提问作者alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:00:32