Optional Eager - redutan/redutan.github.io GitHub Wiki
- 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