What is implementation class of org.springframework.data.jpa.repository.JpaRepository interface?
Tags: spring, springdata
Published: 2024-02-11 14:23:00

## Notice

I wrote this article and was originally published on [Qiita](https://qiita.com/saladlam/items/b166c6771388b6fa995b) on 17 September 2019.

---

From my [notice board example application (Spring Data JPA version)](https://github.com/saladlam/spring-noticeboard/tree/spring-data-jpa). You may notice that only 2 interface is defined only on repository layer

![interface.png](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7rl0b56wqyl6aiawhoky.png)

no implementation class on these interface is defined. So what actual instance is injected into *info.saladlam.example.spring.noticeboard.service.MessageServiceImpl*?

That instance is a proxy, with target class instance *org.springframework.data.jpa.repository.support.SimpleJpaRepository* and many advice/advisor/interceptor is attached. One important interceptor is *org.springframework.data.repository.core.support.RepositoryFactorySupport.QueryExecutorMethodInterceptor*.

Definition of *info.saladlam.example.spring.noticeboard.repository.MessageRepository*

```java
public interface MessageRepository extends JpaRepository<Message, Long> {

	@Query("SELECT m FROM Message m WHERE m.approvedBy IS NOT NULL AND m.publishDate <= :at AND (m.removeDate IS NULL OR m.removeDate > :at) ORDER BY m.publishDate DESC")
	List<Message> findPublished(@Param("at") LocalDateTime at);

	@Query("SELECT m FROM Message m WHERE m.approvedBy IS NULL ORDER BY m.publishDate DESC")
	List<Message> findWaitingApprove();

	@Query("SELECT m FROM Message m WHERE m.owner = :owner ORDER BY m.publishDate DESC")
	List<Message> findByOwner(@Param("owner") String owner);

}
```

and its parent interface *org.springframework.data.jpa.repository.JpaRepository*

```java
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	List<T> findAll();
	List<T> findAll(Sort sort);
	List<T> findAllById(Iterable<ID> ids);
	<S extends T> List<S> saveAll(Iterable<S> entities);
	void flush();
	<S extends T> S saveAndFlush(S entity);
	void deleteInBatch(Iterable<T> entities);
	void deleteAllInBatch();
	T getOne(ID id);

	@Override
	<S extends T> List<S> findAll(Example<S> example);

	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);

}
```

For example, when a method **findAll()** defined in *JpaRepository* is called, as result method **findAll()** of *SimpleJpaRepository* is called. And when a method **findWaitingApprove()** defined in *MessageRepository* is called, interceptor *org.springframework.data.repository.core.support.RepositoryFactorySupport.QueryExecutorMethodInterceptor* is involved. In method **org.springframework.data.repository.core.support.RepositoryFactorySupport.QueryExecutorMethodInterceptor.doInvoke()**

```java
		@Nullable
		private Object doInvoke(MethodInvocation invocation) throws Throwable {

			Method method = invocation.getMethod();
			Object[] arguments = invocation.getArguments();

			if (hasQueryFor(method)) {
				return queries.get(method).execute(arguments);
			}

			return invocation.proceed();
		}
```

**queries** is a map, which store *org.springframework.data.jpa.repository.query.JpaQueryMethod* instance with key method defined in *MessageRepository*.