When using the new Spring Data Evans release it\'s nice to be able to use some of the nice stuff that came with java 8. One of them is default implementations in interfaces. The
Default methods should only be used to delegate calls to other repository methods. Default methods - by definition - cannot access any state of an instance (as an interface has none). They only can delegate to other interface methods or call static ones of other classes.
Actually, using a custom implementation as described in the reference documentation is the right approach. Here's the short version for reference (in case others wonder, too):
/**
* Interface for methods you want to implement manually.
*/
interface UserRepositoryCustom {
Optional findByLogin(String login);
}
/**
* Implementation of exactly these methods.
*/
class UserRepositoryImpl extends QueryDslRepositorySupport implements UserRepositoryCustom {
private static final QUser USER = QUser.user;
@Override
public Optional findByLogin(String login) {
return Optional.ofNullable(
from(USER).
where(
USER.deleter.isNull(),
USER.locked.isFalse(),
USER.login.equalsIgnoreCase(login)).
singleResult(USER));
}
}
/**
* The main repository interface extending the custom one so that the manually
* implemented methods get "pulled" into the API.
*/
public interface UserRepository extends UserRepositoryCustom,
CrudRepository { … }
Be aware that the naming conventions are important here (but can be customized if needed). By extending QueryDslRepositorySupport
you get access to the from(…)
method so that you don't have to interact with the EntityManager
yourself.
Alternatively you can let UserRepository
implement QueryDslPredicateExecutor
and hand in the predicates from outside the repository but that'd let you end up with the clients needing to work with Querydsl (which might be unwanted) plus you don't get the Optional
wrapper type OOTB.