-
Notifications
You must be signed in to change notification settings - Fork 0
Optional Eager
정명주(myeongju.jung) edited this page Dec 22, 2017
·
7 revisions
- OneToOne(child) : EAGER
- OneToOne(parent) : LAZY
- OneToMany : LAZY
- ManyToOne : EAGER
// FIXME 위 내용이 맞는지 확인요망
모든 로딩 전략은 LAZY로 설정하고, 필요에 따라서 EAGER 설정을 하는 것이 나은 것 같다.
-
fetchJoin()
을 이용하면 됨 - querydsl version :
4.1.4
기준
NoticeRepositoryImpl.java
public NoticeRepositoryImpl extends BaseRepositorySupport implements NoticeCustomRepository {
// ...
public Page<NoticeListDetail> findListDetails(Predicate predicate, Pageable pageable) {
QNotice notice = QNotice.notice;
QPartner partner = QPartner.partner;
JPQLQuery<NoticeListDetail> innerQuery = from(notice)
.innerJoin(notice.partner, partner)
.fetchJoin() // EAGER 로딩
.where(predicate)
.select(new QNoticeListDetail(notice, partner));
return queryToPage(innerQuery, pageable);
}
만약 모든 join에 대해서 즉시로딩 전략을 취하고 싶으면
fetchAll()
연산자를 사용
BaseRepositorySupport.java
/**
* 공통 저장소 서포트
* 상속을 통해서 공통코드를 관리
*
* @author myeongju.jung
*/
public abstract class BaseRepositorySupport extends QueryDslRepositorySupport {
public BaseRepositorySupport(Class<?> domainClass) {
super(domainClass);
}
/**
* 일반 JPQLQuery를 Page로 변환
*
* @param query 내부 JPQLQuery
* @param pageable 페이징 인자
* @param <T> 반환 타입
* @return 페이징 결과
*/
protected final <T> Page<T> queryToPage(JPQLQuery<T> query, Pageable pageable) {
long count = query.fetchCount();
List<T> content = Collections.emptyList();
if (count > 0) {
content = getQuerydsl().applyPagination(pageable, query).fetch();
}
return new PageImpl<>(content, pageable, count);
}
}
AdRepository.java
public interface AdRepository extends JpaRepository<Ad, Long>, QueryDslPredicateExecutor<Ad> {
@EntityGraph("Ad.withCompany")
Page<Ad> findAll(Predicate predicate, Pageable pageable);
}
Ad.java
@Entity
@NamedEntityGraph(name = "Ad.withCompany", attributeNodes = @NamedAttributeNode("company"))
// ...
public class Ad {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AD_SEQ")
@Column(name = "AD_NO")
private Long adNo;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COMPANY_NO", nullable = false, updatable = false,
foreignKey = @ForeignKey(name = "FK_AD_COMPANY_NO"))
private Company company;
// ...
}
-
@EntityGraph("Ad.withCompany")
때문에 바로 ad와 company가 join(EAGER) 되어 조회된다. -
@EntityGraph
에서 연관관계 로딩 전략을 직접 설정하기 보다는 해당 Entity에서@NamedEntityGraph
로 선언한 것을 가져다 쓰는 것을 추천- 대부분의 경우 재사용하게 되는 경우가 많으며, 연관관계에 대한 로딩 전략을 Entity에서 관리할 수 있다.
- 만약 위와 같은 도메인 모델 상황에서
Ad
목록을 조회할 시Company
뿐만 아니라Partner
까지 즉시(EAGER) 로딩할려면?
AdRepository.java
public interface AdRepository extends JpaRepository<Ad, Long>, QueryDslPredicateExecutor<Ad> {
@EntityGraph("Ad.withCompanyAndPartner")
Page<Ad> findAll(Predicate predicate, Pageable pageable);
}
Ad.java
@Entity
@NamedEntityGraph(name = "Ad.withCompanyAndPartner",
attributeNodes = @NamedAttributeNode(value = "company", subgraph = "companyWithPartner"),
subgraphs = @NamedSubgraph(name = "companyWithPartner", attributeNodes = @NamedAttributeNode("partner")))
// ...
public class Ad {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AD_SEQ")
@Column(name = "AD_NO")
private Long adNo;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COMPANY_NO", nullable = false, updatable = false,
foreignKey = @ForeignKey(name = "FK_AD_COMPANY_NO"))
private Company company;
// ...
}
-
@NamedEntityGraph
설정이 핵심. 해당 부분에서Ad -> Company -> Partner
까지 객체그래프 설정
// TODO
@startuml
class Partner {
}
class Company {
-partner:Partner
-ads:List<Ad>
}
class Ad {
-company:Company
}
Partner <-- "*" Company
Company <--> "*" Ad
@enduml
JAVA
JPA
- JPA-Create-And-Update
- Optional-Eager
- QueryDsl-Configuration
- QueryDsl-More-Type-safety
- QueryDsl-SubQuery
DDD
Install
Spring
Spring-Boot
- Swagger2-Configuration
- Spring-Restdocs-Configuration
- Spring-Page-Jackson
- JSR310-Guide
- logback-spring.xml
- WebMvcUtils.java
- Spring-Boot-Properties
- Spring-Boot-Hidden-Gems
- Spring-Boot-Config
Spring-Cloud
- Spring-Cloud-Zuul
- Spring-Cloud-Feign
- Spring-Cloud-Hystrix
- Spring-Cloud-Consul
- Spring-Cloud-Ribbon
- Spring-Cloud-Circuit-Breaker
JavaScript
Gradle
Test
Linux
Etc
TODO http://zoltanaltfatter.com/2017/06/09/publishing-domain-events-from-aggregate-roots/