스프링 데이터 JPA-05.스프링 데이터 JPA 원리
스프링 데이터 JPA 원리
JpaRepository<Entity, Id> 인터페이스
- 매직 인터페이스
- @Repository가 없어도 빈으로 등록해 줌.
@EnableJpaRepositories
- 원래라면 설정파일 만들어 넣어주어야 하나, 부트가 자동설정.
- 시작은 여기서 부터
@Import(JpaRepositoriesRegistrar.class) public @interface EnableJpaRepositories { ...
동작 원리
- 시작은 @Import(JpaRepositoriesRegistrar.class)
@EnableJpaRepositories 안에 들어있음.
해당 클래스에 가보면 (JpaRepositoriesRegistrar)
/**
* {@link ImportBeanDefinitionRegistrar} to enable {@link EnableJpaRepositories} annotation.
*
* @author Oliver Gierke
*/
class JpaRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
/*
- 핵심은 ImportBeanDefinitionRegistrar 인터페이스
JPA 레지스터를 빈으로 등록해줌
빈 데피니션을 정의할 수 있는 인터페이스 - 스프링 프레임워크의 일부 요소.
어떤 동작을 하나면, 빈을 프로그래밍으로 동작할 수 있게 해준다.
즉, 프로그래밍을 통해 JpaRepository 또는 해당 상위 클래스인 Repository의 인터페이스를 상속받은 모든 인터페이스를 찾아서, 해당 타입의 민들을 등록해 줄 수 있다.
예제 코드
public class Jaeuk {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class JaeukRegister implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(Jaeuk.class);
beanDefinition.getPropertyValues().add("name", "jaeuk");
registry.registerBeanDefinition("jaeuk", beanDefinition);
}
}
@SpringBootApplication
@Import(JaeukRegister.class)
public class JpaApplication {
public static void main(String[] args) {
SpringApplication.run(JpaApplication.class, args);
}
}
@Component
public class JpaRunner implements ApplicationRunner {
@Autowired
Jaeuk jaeuk;
@Override
public void run(ApplicationArguments args) {
System.out.println("================");
System.out.println(jaeuk.getName());
}
================
jaeuk
빈으로 등록하지 않았음에도 불구하고 Jaeuk 클래스도 빈으로 등록 및 Autowired로 사용하는 것을 확인할 수 있다.
이런 방식으로, ImportBeanDefinitionRegistrar가 JpaRepository를 구현한 것 (빈으로 등록)
@EnableJpaRepositories 타고 들어가서 추적해보면 직접 확인 가능.
이 외에도 애노테이션의 정보들도 참조해서,
어느 패키지부터 참조할건지, 필터 어떤 것들은 제외시키고, 어떤 건 추가시킬지, 베이스 url 등..
이런 다음에 최종적으로 빈으로 등록하는 것.
핵심 개념 마무리
데이터베이스와 자바 패러다임 불일치 ORM이란? JPA 사용법 (엔티티, 벨류 타입, 관계 맵핑) JPA 특징 (엔티티 상태 변화, Cascade, Fetch, 1차 캐시, …) 주의할 점
- 반드시 발생하는 SQL을 확인할 것.
- 팁: “?”에 들어있는 값 출력하기
- logging.level.org.hibernate.SQL=debug
- logging.level.org.hibernate.type.descriptor.sql=trace
select
post0_.id as id1_2_0_,
post0_.title as title2_2_0_
from
post post0_
where
post0_.id=?
Hibernate:
select
post0_.id as id1_2_0_,
post0_.title as title2_2_0_
from
post post0_
where
post0_.id=?
2019-12-28 14:23:06.416 TRACE 27610 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [2]
binding parameter [1] as [BIGINT] - [2]
값 확인.
spring.datasource.url=jdbc:postgresql://localhost:5432/springdata
spring.datasource.username=jaeuk
spring.datasource.password=pass
# drop - create
spring.jpa.hibernate.ddl-auto=create
# sql show
spring.jpa.show-sql=true
# sql show할 때 포멧 (보 기편하게)
spring.jpa.properties.hibernate.format_sql=true
#warning 제거
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
# sql show(동일)
-logging.level.org.hibernate.SQL=debug
# ? 값 확인
-logging.level.org.hibernate.type.descriptor.sql=trace