@Repository
public interface SurveyRepository extends JpaRepository<Survey, Long> {
}
먼저 위와 같이 JPA repository를 엔티티에 맞게 구현해두었다고 가정한다.
그렇다면 매번 @Repository annotation을 붙여야할까?
정답은 아니다!
그렇다면 왜 JpaRepository는 annotation이 없어도 Bean 등록이 되는지 살펴봅시다.
구현체 살펴보기
우선 작성된 엔티티에 관하여 repository를 구현한다하면 일반적으로 JpaRepository의 interface를 상속받는다.
그렇다면 여기서 JpaRepository가 어떻게 생겼는지 살펴보자
JpaRepository
위와 같이 생겼는데 JpaRepository의 왼쪽 화살표를 눌러보아 구현 클래스들의 목록을 살펴보자.
그러면 위에 SimpleJpaRepository가 나와있는데 해당 클래스로 이동한다.
SimpleJpaRepository
SimpleJpaRepository를 살펴보면 이미 @Repository 애노테이션이 붙어있는 것을 볼 수 있다.
또한 Transactional annotation도 붙어있다.
결론
JpaRepository 인터페이스의 구현체 클래스인 SimpleJpaRepository가 스프링 빈으로 등록되어 있어서 별도의
@Repository annotation을 붙이지 않아도 정상적으로 Bean으로 등록되는 것이다.
그렇다면 Transaction annotation은?
JpaRepository는 또한 ListCrudRepository를 상속받는다.
ListCrudRepository
@NoRepositoryBean
public interface ListCrudRepository<T, ID> extends CrudRepository<T, ID> {
<S extends T> List<S> saveAll(Iterable<S> entities);
List<T> findAll();
List<T> findAllById(Iterable<ID> ids);
}
CrudRepository를 상속받는데 이를 살펴보자
CrudRepository
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
따라서 여기에 구현된 save, findById 등등 간단한 CRUD에 대해서는 아까 살펴보았듯이 Transaction annotation이 붙어있기에 기본적으로 Transaction이 활성화된다.
참고 공식문서
https://docs.spring.io/spring-data/jpa/reference/jpa/transactions.html