首页 > 解决方案 > 将多对多 IN 语句映射到 JPA(Spring Boot)

问题描述

我在 JPA 中创建了两个实体,ListingItemType - 它们存在于多对多关系中(Hibernate 自动生成连接表)。我正在尝试找到创建查询的最佳方法,该查询接受项目类型字符串的动态列表并返回与指定项目类型匹配的所有列表的 ID,但我是 JPA 中的新人。

目前我正在使用 JpaRepository 创建相对简单的查询。我一直在尝试使用 CriteriaQuery 来做到这一点,但我在其他地方读到的一些接近但不完全的答案似乎表明,因为这是在 Spring 中,这可能不是最好的方法,我应该使用JpaRepository 实现本身。这看起来合理吗?

我有一个感觉不到一百万英里的查询(基于 Baeldung 的示例和我在WikiBooks上的阅读),但对于初学者来说,我在 Join 上收到 Raw Type 警告,更不用说我不确定这是否会运行,我确信有更好的方法来解决这个问题。

public List<ListingDTO> getListingsByItemType(List<String> itemTypes) {

    List<ListingDTO> listings = new ArrayList<>();

    CriteriaQuery<Listing> criteriaQuery = criteriaBuilder.createQuery(Listing.class);

    Root<Listing> listing = criteriaQuery.from(Listing.class);
    //Here Be Warnings. This should be Join<?,?> but what goes in the diamond?
    Join itemtype = listing.join("itemtype", JoinType.LEFT);

    In<String> inClause = criteriaBuilder.in(itemtype.get("name"));

    for (String itemType : itemTypes) {

        inClause.value(itemType);

    }

    criteriaQuery.select(listing).where(inClause);

    TypedQuery<Listing> query = entityManager.createQuery(criteriaQuery);

    List<Listing> results = query.getResultList();

    for (Listing result : results) {

        listings.add(convertListingToDto(result));

    }

    return listings;

}

我试图了解如何最好地传递names 的动态列表(ItemType 中的字段)并返回一个唯一ids 列表(Listing 中的 PK),其中有一行在联结表中匹配。如果我可以提供任何进一步的信息或帮助,请告诉我 - 我已经感觉到 JPA 及其对此类动态查询的处理是其生计的一部分!

标签: spring-bootjpapersistence

解决方案


当您需要根据各种...条件动态创建查询时,条件 API 很有用。

您只需要一个静态 JPQL 查询:

select distinct listing from Listing listing 
join listing.itemTypes itemType 
where itemType.name in :itemTypes

由于您使用的是 Spring-data-jpa,因此您只需要定义一个方法并@Query在存储库接口中对其进行注释:

@Query("<the above query>")
List<Listing> findByItemTypes(List<String> itemTypes)

推荐阅读