简体   繁体   中英

Dynamic Query JPA 2 Specification With CriteriaBuilder

I have below table data:

Product Reason Qty
Pepsi   IN     10
Pepsi   Out    2
Pepsi   In     15
Pepsi   Out    5 
Coke    IN     100
Coke    Out    20
Coke    In     35
Coke    Out    25
Fanta   Out     55

and I want to get result like below:

Product Qty
Pepsi   18
Coke    90
Fanta   -55

for that I have got below query:

SELECT Product,
       SUM(CASE WHEN reason IN ('IN','REFUND') THEN Qty 
                WHEN reason IN ('OUT','WASTE') THEN -Qty
                ELSE NULL END) AS Qty
FROM stock
GROUP BY Product;

I want to use JPA Specification like used in this link , I am new to JPA Specification can someone please guide me?

I have got this link and this link but I am not sure what is the correct question to solve the problem?

EDIT:

I have tried below code

@Override
    public Predicate toPredicate(Root<Stockdiary> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

    Path reasonexpression = root.get("reason");
                    Path qtyexpression = root.get("qty");

                    List<String> inList = new ArrayList<String> ();
                    inList.add("IN");

                    List<String> outList = new ArrayList<String> ();
                    outList.add("OUT");

                    Predicate inpredicate = reasonexpression.in(inList);
                    Predicate outpredicate = reasonexpression.in(outList);

                    Expression<Number> sum = builder.sum(
                            builder.<Number>selectCase()  
                                 .when(inpredicate,qtyexpression.as(Double.class))  
                                 .when(outpredicate,builder.neg(qtyexpression).as(Double.class))  
                                 .otherwise(0));

return builder.equal(sum.as(Integer.class), 1)
}

Call it from as pageable

Page<Stockdiary> page = stockRepository.findAll(spec,pageable);

which is making below query :-

select count(stock0_.stock_id) as col_0_0_ from stock stock0_ cross join session_tbl session_tb1_ 
where stock0_.session_id=session_tb1_.session_id and 
cast(sum(case when stock0_.reason in (?) then stock0_.qty when stock0_.reason in (?) then -stock0_.qty else 101 end) as signed)=1 
group by stock0_.reason , stock0_.products_id , session_tb1_.terminal_id

I am getting SQL Exception due to case statement is after where clause. I dont know why spring put case after the where clause.

I am trying to make dynamic query, as i cant use static query.

Essentially you are looking to perform a Native Query .

In particular, you could use the JPA feature SqlResultSetMapping to define the mapping between your native query and the DTO object that can hold your data.

Assuming the DTO for your needs looks like this:

class ProductQuantity {
   private String product;
   private Integer quantity;

   public ProductQuantity(String product, Integer quantity) {
      this.product = product;
      this.quantity = quantity;
   }

   public getProduct() { return this.product; }

   public getQuantity() { return this.quantity; }
}

The following definition can act as a mapping for the native query:

@SqlResultSetMapping(
   name = "ProductQuantityMapping",
   classes = @ConstructorResult(
         targetClass = ProductQuantity.class,
         columns = {
            @ColumnResult(name = "product", type = String.class),
            @ColumnResult(name = "qty", type = Integer.class)
         })
)

And finally the query can be invoked as:

Query q = entityManager.createNativeQuery("SELECT Product,SUM(CASE WHEN reason IN ('IN','REFUND') THEN Qty WHEN reason IN ('OUT','WASTE') THEN -Qty ELSE NULL END) AS Qty FROM stock GROUP BY Product");

List<ProductQuantity> result = q.getResultList();

for(ProductQuantity pq : result) {
   System.out.println("product: " + pq.getProduct() + ", Quantity: " + pq.getQuantity());
}

For more information/examples take a look at this article .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM