When working with Spring Boot and JPA, I’m a fan of declaring simple repository interfaces. But what if you want to reference a static code variable in the query, instead of typing it in manually, which is errorprone and not refactor-friendly? Here’s how.
The challenge
Here’s a typical JPA interface, with a custom query:
public interface OrdersRepository {
@Query("SELECT COUNT(*) FROM Orders as O WHERE O.amount > :threshold")
long getLargeOrderCount(
@Param("threshold")final long threshold);
}
/**
* Calling the repository
*/
ordersRepository.getLargeOrderCount(Constants.LARGE_ORDER_THRESHOLD);
Now, wouldn’t it be nice to be able to pass in the static threshold value to the query, but without having to type it in manually as in the method call illustrated above? Default methods to the rescue. Here’s what you do:
/**
* Add a default method to your interface that references the static threshold value, and calls the original method (which has been slightly renamed).
*/
public interface OrdersRepository {
@Query("SELECT COUNT(*) FROM Orders as O WHERE O.amount > :threshold")
long doGetLargeOrderCount(
@Param("threshold")final long threshold);
long getLargeOrderCount() {
return doGetLargeOrderCount(Constants.LARGE_ORDER_THRESHOLD);
}
}
/**
* Now calling the method on the JPA interface can be simplified:
*/
ordersRepository.getLargeOrderCount();
The details
As it says in the Oracle Java documentation:
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
And that’s exactly how we can utilize it here to have the query reference code instead of manually typing in text directly in the query.
Summary
As you can see this is an easy way to reference constants, static values etc. in your repository interface to make calling methods easier. The above code is just an example, but pretty convenient if you ask me.