본문 바로가기

Spring/DB

@Repository 기능

@Repository 는 데이터 액세스 계층에서 사용되는 애너테이션이다. 보통은 컴포넌트 스캔의 대상이 되기 위해 적용하지만 스프링 부트와 JPA 를 사용할 경우 예외 변환기(PersistenceExceptionTranslationPostProcessor) 를 자동으로 등록해서 @Repository 를 적용한 빈을 프록시로 변환한다. 이렇게 변환된 프록시는 데이터 액세스 계층에서 예외가 발생하면 스프링 예외 추상화(DataAccessException)로 변환해준다. 

 

스프링 예외 추상화로 변환 시 이점은 JPA 뿐만 아니라 JdbcTemplete, MyBatis 와 같은 데이터 접근 기술에서 발생되는 예외를 통합적으로 관리한다는 점이다. 따라서 데이터 접근 기술을 변경하더라도 예외 처리하는 로직을 수정할 필요가 없게 된다.

테스트

@Slf4j
@Component
public class ItemRepository {

    private final EntityManager em;

    public ItemRepository(EntityManager em) {
        this.em = em;
    }

    @Override
    public List<Item> findAll() {
        return em.createQuery("selectt i from Item i", Item.class)
                .getResultList();
    }
}


@Slf4j
@Repository
public class ItemRepository {

    private final EntityManager em;

    public ItemRepository(EntityManager em) {
        this.em = em;
    }

    @Override
    public List<Item> findAll() {
        return em.createQuery("selectt i from Item i", Item.class)
                .getResultList();
    }
}


@Slf4j
@SpringBootTest
class ItemRepositoryTest {
    @Autowired
    ItemRepository repository;

    @Test
    void selectItem() {
        log.info("repository = {}", repository.getClass());
        List<Item> all = repository.findAll();
    }
}

 

테스트는 select 함수가 오타 났을 때 발생하는 오류를 확인해보려고 한다.

첫 번째 테스트 클래스는 @Component 를 적용하였고 두 번째 테스트 클래스는 @Repository 를 적용하였다.

테스트코드에서는 클래스의 정보와 조회하는 코드를 작성하였다.

 

@Component 를 적용한 클래스  결과

repository = class jpa.JpaItemRepository
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException

 

@Repository 를 적용한 클래스  결과

repository = class jpa.JpaItemRepository$$EnhancerBySpringCGLIB$$6f682d37
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException

두 테스트를 비교해보면 @Repository 를 적용했을 때 프록시로 빈을 등록한 것과 스프링 예외 추상화로 변경된 것을 알 수 있다.

 

참고로 @Controller 를 적용하면 스프링 프레임워크에 의해 URI와 @RequestMapping 을 비교해 원하는 핸들러를 찾을 수 있게 해준다.

@Service 를 적용하면 별 다른 기능은 없고 @Component 처럼 단순 컴포넌트 스캔의 대상만 된다.