No results returned when using JPA Specifications in(Collection<?>) method

Viewed 439

I'm trying to implement the equivalent of this SQL query using Spring Data JPA Specifications:

SELECT * FROM product WHERE category_id IN (....)

The two entities involved in this query have a OneToMany and ManyToOne relationship:

ProductEntity:

@Data
@NoArgsConstructor
@Entity
@Table(name = "PRODUCT")
public class ProductEntity extends AbstractAuditableEntity {

    // skipped other properties for simplicity sake

    @ManyToOne
    private CategoryEntity categoryEntity;

}

CategoryEntity:

@Entity
@Table(name = "PRODUCT_CATEGORY")
@Data
public class CategoryEntity extends AbstractBaseEntity {

    // skipped other properties for simplicity sake

    @OneToMany(mappedBy = "categoryEntity")
    private List<ProductEntity> productEntities;

}

My JPA Specifications query compiles and runs without any error, but doesn't return any result: Specification definition:

public static Specification<ProductEntity> inCategories(List<Long> categories) {
    return (root, query, builder) -> {
        if (categories != null && !categories.isEmpty()) {
            final Path<CategoryEntity> category = root.get("categoryEntity");
            return category.get("id").in(categories);
        } else {
            // always-true predicate, means that no filtering would be applied
            return builder.and();
        }
    };
}

Client code:

    Page<ProductEntity> productEntityPage = productRepository.findAll(Specification
                    .where(ProductSpecifications.inCategories(filterCriteria.getCategories()))
            , pageRequest);

Why doesn't it work? I get results when querying the database using SQL statements, so there must be something wrong with either my JPA Specifications query or my entities mapping.

What am I missing?

1 Answers

I think you should use join here

Join<ProductEntity, CategoryEntity> categoryJoin = root.join("categoryEntity");
return categoryJoin.get("id").in(categories);

instead of

Path<CategoryEntity> category = root.get("categoryEntity");
return category.get("id").in(categories);

since root.get("categoryEntity").get("id"); will give you nothing as no such path (product.categoryEntity.id) exists in product table.

Related