package com.querydsl.example.dao;
import com.querydsl.core.dml.StoreClause;
import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.QBean;
import com.querydsl.example.dto.CustomerPaymentMethod;
import com.querydsl.example.dto.Order;
import com.querydsl.example.dto.OrderProduct;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.dml.SQLInsertClause;
import org.springframework.transaction.annotation.Transactional;
import javax.inject.Inject;
import java.util.List;
import static com.querydsl.core.types.Projections.bean;
import static com.querydsl.example.sql.QCustomerOrder.customerOrder;
import static com.querydsl.example.sql.QCustomerOrderProduct.customerOrderProduct;
import static com.querydsl.example.sql.QCustomerPaymentMethod.customerPaymentMethod;
@Transactional
public class OrderDaoImpl implements OrderDao {
@Inject
SQLQueryFactory queryFactory;
final QBean<OrderProduct> orderProductBean = bean(OrderProduct.class,
customerOrderProduct.productId, customerOrderProduct.comments, customerOrderProduct.quantity);
final QBean<Order> orderBean = bean(Order.class,
customerOrder.id, customerOrder.orderPlacedDate, customerOrder.orderPaidDate,
customerOrder.orderStatus, customerOrder.totalOrderPrice,
bean(CustomerPaymentMethod.class, customerPaymentMethod.all()).as("customerPaymentMethod"),
GroupBy.set(orderProductBean).as("orderProducts"));
@Override
public Order findById(long id) {
List<Order> orders = findAll(customerOrder.id.eq(id));
return orders.isEmpty() ? null : orders.get(0);
}
@Override
public List<Order> findAll(Predicate... where) {
return queryFactory.from(customerOrder)
.leftJoin(customerOrder.paymentMethodFk, customerPaymentMethod)
.leftJoin(customerOrder._orderFk, customerOrderProduct)
.where(where)
.transform(GroupBy.groupBy(customerOrder.id).list(orderBean));
}
private <T extends StoreClause<T>> T populate(T dml, Order o) {
return dml.set(customerOrder.customerPaymentMethodId, o.getCustomerPaymentMethod().getId())
.set(customerOrder.orderPlacedDate, o.getOrderPlacedDate())
.set(customerOrder.totalOrderPrice, o.getTotalOrderPrice());
}
@Override
public Order save(Order o) {
Long id = o.getId();
if (id == null) {
id = populate(queryFactory.insert(customerOrder), o)
.executeWithKey(customerOrder.id);
o.setId(id);
} else {
populate(queryFactory.update(customerOrder), o)
.where(customerOrder.id.eq(id))
.execute();
// delete orderproduct rows
queryFactory.delete(customerOrderProduct)
.where(customerOrderProduct.orderId.eq(id))
.execute();
}
SQLInsertClause insert = queryFactory.insert(customerOrderProduct);
for (OrderProduct op : o.getOrderProducts()) {
insert.set(customerOrderProduct.orderId, id)
.set(customerOrderProduct.comments, op.getComments())
.set(customerOrderProduct.productId, op.getProductId())
.set(customerOrderProduct.quantity, op.getQuantity())
.addBatch();
}
insert.execute();
o.setId(id);
return o;
}
@Override
public long count() {
return queryFactory.from(customerOrder).fetchCount();
}
@Override
public void delete(Order o) {
// TODO use combined delete clause
queryFactory.delete(customerOrderProduct)
.where(customerOrderProduct.orderId.eq(o.getId()))
.execute();
queryFactory.delete(customerOrder)
.where(customerOrder.id.eq(o.getId()))
.execute();
}
}