My end to end flow is as given below: controller -> adapter -> persistence/repository -> DB
In my controller:
@RequestMapping(value = "/userOrder/{orderID}", method = RequestMethod.DELETE)
public Set<?> deleteOrder(@PathVariable("orderID") String orderID) {
/*
* orderHandlerAdapter cancels the order and passed list of orders created + cancelled so * far.
*/
Set<Orders> orderList = orderHandlerAdapter.cancelOrder(orderID);
return orderList;
}
In adapter:
public Set<Order> cancelOrder(String orderID) {
/*
* Cancel order first.
*/
userOrderRepository.saveOrder(orderID,"CANCELLED");
/*
* Return list of orders created and cancelled so far.
*/
Set<Order> orderList = userOrderRepository.getFirstByOrderIdAndStatusCdIsIn(orderID, new Set<String> {"CREATED","CANCELLED"});
return Set<Order>;
}
In persistence:
public interface orderRespository extends CrudRepository<UserOrder,String>() {
/*
* Save status = CANCELLED into the DB.
*/
void saveOrder(String orderID);
/*
* Get orders that are created and cancelled.
*/
Set<Order> getFirstByOrderIdAndStatusCdIsIn(String orderID, new Set<String> orderStatusSet);
}
I find that when saveOrder/getFirstByOrderIdAndStatusCdIsInis called, the queries are not defined anywhere, and the interface is not implemented either. But the result is returned correctly.
How does this work? Is JPA intelligent enough to create queries based on the method names?
Spring Data has a default implementation for the methods from the repositories included in the product (CrudRepository
, PagingAndSortingRepository
, JpaRepository
, QueryByExampleExecutor
). You can find many in the SimpleJpaRepository
.
But it is not just that an instance of SimpleJpaRepository
gets added to the ApplicationContext
. instead, a proxy is used. The proxy checks the method being called and decides how to provide an implementation:
@Query
annotation or does its name match a named query -> call thatBeyond that Spring Data takes care of conversions between results of the queries and the required return type of the method.