0

I've this CTE which I'd implement in Java:
It's running on an IBM Iseries 7.3 DB2 machine.

WITH params (from_date, to_date, outlet, product_number)
AS (
    values(TO_DATE('01.11.2018', 'DD.MM.YYYY'),
        TO_DATE('18.12.2018', 'DD.MM.YYYY'),
        'BLK' ,
        49 )
    ),
product
AS (
    SELECT DISTINCT cpp.competitor_products_id product
    FROM yxdb.competitor_product_prices cpp
    INNER JOIN yxdb.competitor_products_comparisons cpc ON cpc.competitor_products_id = cpp.competitor_products_id
        AND cpc.deleted = 0
    INNER JOIN yxdb.outlets o ON o.outlets_id = cpc.outlets_id
        AND o.deleted = 0
    INNER JOIN params ON cpp.price_date > params.from_date
        AND cpc.product_number = params.product_number
        AND o.short_name = params.outlet
    WHERE cpp.deleted = 0
    )
select * from product;

It's a lot longer, so the params table is used several times.
When implementing it in Java, I replace the hardcoded dates and other parameters in Java as ?1, ?2 etc. I've also tried with named parameters, none works. They all give [SQL0418] Use of parameter marker or NULL not valid.

Java Code snippet:

@RepositoryRestResource
    public interface CompetitorPriceDateRepository extends JpaRepository<CompetitorPriceDateEntity, Long> {
    @Query(value = "WITH params (from_date, to_date, outlet, product_number) "
                + " AS ( "
                + "     values(TO_DATE( :fromDate , 'DD.MM.YYYY'), "
                + "         TO_DATE( :toDate , 'DD.MM.YYYY'), "
                + "         :outlet , "
                + "         :productNumber ) "
                + "     ), "
                + " product "
                + " AS ( "
                + "     SELECT DISTINCT cpp.competitor_products_id product "
                + "     FROM yxdb.competitor_product_prices cpp "
                + "     INNER JOIN yxdb.competitor_products_comparisons cpc ON +" cpc.competitor_products_id = cpp.competitor_products_id "
                + "         AND cpc.deleted = 0 "
                + "     INNER JOIN yxdb.outlets o ON o.outlets_id = cpc.outlets_id "
                + "         AND o.deleted = 0 "
                + "     INNER JOIN params ON cpp.price_date > params.from_date "
                + "         AND cpc.product_number = params.product_number "
                + "         AND o.short_name = params.outlet "
                + "     WHERE cpp.deleted = 0 "
                + "     ) "
                + " select * from product ",nativeQuery = true) 
    List<CompetitorPriceDateEntity> findAllInterpolatedByDates(
                    @Param("productNumber") Integer productNumber,
                    @Param("outlet") String outlet,
                    @Param("fromDate") String fromDate,
                    @Param("toDate") String toDate
            );
Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
Anders Metnik
  • 6,096
  • 7
  • 40
  • 79

1 Answers1

0

Without the stack trace I dont' have any aidea what's wrong with your query. SQL seems solid.

Try with a named native query

@Entity
@NamedNativeQuery(
        name = “competitor.findProducts.byDateOutletProductnumber", 
        query = "WITH params (from_date, to_date, outlet, product_number) "
            + " AS ( "
            + "     values(TO_DATE( :fromDate , 'DD.MM.YYYY'), "
            + "         TO_DATE( :toDate , 'DD.MM.YYYY'), "
            + "         :outlet , "
            + "         :productNumber ) "
            + "     ), "
            + " product "
            + " AS ( "
            + "     SELECT DISTINCT cpp.competitor_products_id product "
            + "     FROM yxdb.competitor_product_prices cpp "
            + "     INNER JOIN yxdb.competitor_products_comparisons cpc ON +" cpc.competitor_products_id = cpp.competitor_products_id "
            + "         AND cpc.deleted = 0 "
            + "     INNER JOIN yxdb.outlets o ON o.outlets_id = cpc.outlets_id "
            + "         AND o.deleted = 0 "
            + "     INNER JOIN params ON cpp.price_date > params.from_date "
            + "         AND cpc.product_number = params.product_number "
            + "         AND o.short_name = params.outlet "
            + "     WHERE cpp.deleted = 0 "
            + "     ) "
            + " select * from product ", 
        hints = { 
            @QueryHint(name = "org.hibernate.cacheable", value = "true") })
public class CompetitorPriceDateEntity { ... }

pro bonus 1: Named queries are sort of precompiled, so jpa doesn't need to compile the query into a executable criteria every time it gets called.

pro bonus 2: Query hint cacheable or eclipselink equivalent

JJCV
  • 326
  • 2
  • 19