How to add custom method to Spring Data JPA
You need to create a separate interface for your custom methods:
public interface AccountRepository extends JpaRepository<Account, Long>, AccountRepositoryCustom { ... }public interface AccountRepositoryCustom { public void customMethod();}
and provide an implementation class for that interface:
public class AccountRepositoryImpl implements AccountRepositoryCustom { @Autowired @Lazy AccountRepository accountRepository; /* Optional - if you need it */ public void customMethod() { ... }}
See also:
Note that the naming scheme has changed between versions. See https://stackoverflow.com/a/52624752/66686 for details.
In addition to axtavt's answer, don't forget you can inject Entity Manager in your custom implementation if you need it to build your queries:
public class AccountRepositoryImpl implements AccountRepositoryCustom { @PersistenceContext private EntityManager em; public void customMethod() { ... em.createQuery(yourCriteria); ... }}
The accepted answer works, but has three problems:
- It uses an undocumented Spring Data feature when naming the custom implementation as
AccountRepositoryImpl
. The documentation clearly states that it has to be calledAccountRepositoryCustomImpl
, the custom interface name plusImpl
- You cannot use constructor injection, only
@Autowired
, that are considered bad practice - You have a circular dependency inside of the custom implementation (that's why you cannot use constructor injection).
I found a way to make it perfect, though not without using another undocumented Spring Data feature:
public interface AccountRepository extends AccountRepositoryBasic, AccountRepositoryCustom { }public interface AccountRepositoryBasic extends JpaRepository<Account, Long>{ // standard Spring Data methods, like findByLogin}public interface AccountRepositoryCustom { public void customMethod();}public class AccountRepositoryCustomImpl implements AccountRepositoryCustom { private final AccountRepositoryBasic accountRepositoryBasic; // constructor-based injection public AccountRepositoryCustomImpl( AccountRepositoryBasic accountRepositoryBasic) { this.accountRepositoryBasic = accountRepositoryBasic; } public void customMethod() { // we can call all basic Spring Data methods using // accountRepositoryBasic }}