JPA Repository 원리 및 사용

LSM ·2021년 9월 1일
0
post-custom-banner

글 작성 계기

흔히 spring에서는 아래와 같은 간단한 방법으로 jpaRepository 인터페이스를 만들 수 있다.

public interface PostRepository extends JpaRepository<Post, Long> {
}

@Autowired
PostRepository postRepository;

궁금 했던 점은 위와 같이 설정 후 다른 클래스에서 해당 jpaRepository를 DI(의존성 주입)을 통해 사용하곤 했는데 jpaRepository가 언제 어떻게 Spring의 Bean에 등록이 되는지 궁금해서 찾아보게 된 글을 정리 하겠다.


JPA Repository가 bean에 등록 되는 과정

핵심은 ImportBeanDefinitionRegistrar​ 인터페이스이다.

ImportBeanDefinitionRegistrar
1. SpringFrameWork의 인터페이스이며 구현체가 다양함
2. 빈을 프로그래밍을 통해서 등록할 수 있게 해줌
3. JpaRepository를 상속받은 모든 인터페이스들을 찾아서 빈으로 등록해줌

예제 ) Freelife를 빈으로 등록하는 예제

  1. Freelife 클래스 구현
public class Freelife {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. FreelifeRegistrar 클래스 구현 - 빈으로 등록하는 프로그래밍 과정
public class FreelifeRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(Freelife.class);
        beanDefinition.getPropertyValues().add("name", "Superman");

        registry.registerBeanDefinition("freelife", beanDefinition);
    }
}
  1. @Import 설정 - 최종적으로 아래와 같이 설정하면 프로그래밍에 의해서 자동으로 빈으로 등록됨
@SpringBootApplication
@Import(FreelifeRegistrar.class)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
  1. 등록된 빈을 주입받아서 출력 테스트
@Component
@Transactional
public class JpaRunner implements ApplicationRunner {

    @Autowired
    Freelife freelife;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("=====================");
        System.out.println(freelife.getName());
    }
}

JPA Repository 예전의 방식

  • EntityManager로 복잡하게 구현
  • 코드도 작성하고 테스트도 해야되고 매우 번거로움
@Repository
@Transactional
public class PostRepository {

    @PersistenceContext
    EntityManager entityManager;

    public Post add(Post post) {
        entityManager.persist(post);
        return post;
    }

    public void delete(Post post) {
        entityManager.remove(post);
    }

    public List<Post> findAll() {
        return entityManager.createQuery("SELECT p FROM Post AS p", Post.class)
                .getResultList();
    }
}

JPA Repository 현재의 방식

  • 개별 interface를 만들고 JpaRepository라는 interface를 상속받음
  • JpaRepository 첫번째 타입은 Entity 타입이고 두번째 타입은 Entity에서 사용하는 PK의 Type
  • @EnableJpaRepositories 는 스프링부트가 자동 설정해줌
  • 아래와 같이 구현하면 @Repository를 지정할 필요없이 빈으로 등록됨
  • EntityManager로 복잡하게 구현했던 Code를 SpringDataJPA를 통해 안정적으로 검증된 Code를 사용하여 간결하게 구현가능
  • 생산성, 유지보수성, 코드의 간결함, 간결한 코드로 인해 테스트 작성이 불필요함
public interface PostRepository extends JpaRepository<Post, Long> {
}

참고자료 : https://freedeveloper.tistory.com/131?category=809237

  • JpaRepository<Entity, Id> 인터페이스의 전반적인 설명이 잘 되어있음!
profile
개발 및 취준 일지
post-custom-banner

0개의 댓글