String query = "select m.username from Member m";
String query = "select m.team.name from Member m";
>> team에서 타고 타고 값을 찾을 수 있다.
String query = "select t.members from Team t";
String query = "select m from Member m";
List<Member> result = em.createQuery(query, Member.class)
.getResultList();
for (Member member : result) {
System.out.println("member = " + member.getUsername()+", "+ member.getTeam().getName());
//회원1, 팀A(SQL)
//회원2, 팀A(1차 캐시)
//회원3, 팀B(SQL)
}
>> 위 코드는 getTeam().getName()을 호출할 때 Team 조인 쿼리를 실행
>> 회원 100명을 조회하면 조인 쿼리가 100번까지 나갈 수 있음 -> N+1 문제
String query = "select m from Member m join fetch m.team";
>> 한번의 조인 쿼리로 연관된 데이터를 가져온다.
@BatchSize(size = 100)
@OneToMany(mappedBy = "team", fetch = FetchType.LAZY)
private List<Member> members = new ArrayList<>();
---------------------------------------------------------------
<property name="hibernate.default_batch_fetch_size" value="100" />
===> 여러 테이블을 조인해서 엔티티가 가진 모양이 아닌 전혀 다른 결과를 내야하면 페치 조인 보다는 일반 조인을 사용하고 필요한 데이터들만 조회해서 DTO로 반환하는 것이 효과적인다.
@Entity
@NamedQuery(
name ="Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
-----------------------------------------------------------------------
List<Member> memberList = em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", member1.getUsername())
.getResultList();
int count = em.createQuery("update Member m set m.age = 20")
.executeUpdate();
- 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리 -> 업데이트를 해도 1차 캐시는 수정이 되어있지 않는다.
-> 벌크 연산을 먼저 수행 후 영속성 컨텍스트 초기화 -> em.clear() 후 db 다시 조회