select t.*, m.* from Team t inner join Member m on t.team_id = m.team_id;
select t.* from Team t inner join Member m on t.team_id = m.team_id;
t.*, m.*
으로 조회하는게 아니라 쿼리를 한번 더 보낸다select t from Team t join fetch t.members join fetch t.foods
cannot simultaneously fetch multiple bags:
select m from Member m join fetch m.team join fetch m.group1
대신 member, team group1이 모두 있는것만 가져오게 됨
만약 team,group1이 없어도 가져오고싶다면..? 어떻게 해야할까?
.
을 찍어서 객체그래프 탐색하는 것
select o.member from Order o
묵시적 조인: 경로표현식에 의해 묵시적으로 조인이 일어나는 것
명시적 조인: join을 적어주는 조인
select t.members from Team t
-> 성공
select t.members.name from Team t
-> 실패
select m.username from Team t join t.members m
select m from Member m where m.age > (select avg(m.age) from Member m
select m from Member m where (select count(o) from Order o where o.member = m) > 0
select m from Member m where exists (select t from m.team t where t.name = '팀A'
select o from Order o where o.orderAmount < ALL (select p.productAmount from Product p)
select m from Member m where m.team = ANY (select t from Team t)
select t from Team t where t IN (select m.team from Member m where m.age >= 20)
select t from Team t where t IN (select t2 From Team t2 join t2.members m2 where m2.age >= 20)
-> 결과 같게 나오는데 같은 쿼리인게 맞을까?
-> 근데 이게 서브쿼리의 결과는 다른데 in을썼기때문에 같은결과가 나오는거일까요?
-> select m from Member m where m In (서브쿼리)
이런 쿼리면 항상 결과는 중복이 없나요?(id값이 같은 member가 여러건 조회)
select m.username from Member m where m.type = jpql.MemberType.ADMIN
em.createQuery("select m.username from Member m where m.type =:type")
.setParameter("type", MemberType.ADMIN).getResultMap();
select p from Person p where Type(p) = Student
@Test
@Transactional
public void 상속(){
//given
Student student = new Student(12, "학생1");
Teacher teacher = new Teacher("교감", "김교감");
em.persist(student);
em.persist(teacher);
em.flush();
em.clear();
//when
List<Person> personList = em.createQuery("select p from Person p where Type(p) = Student", Person.class).getResultList();
//then
for (Person p: personList) {
System.out.println(p.getName() + " " + ((Student) p).getAge());
}
}
=
으로 비교하면 안되고 반드시 IS NULL을 사용해야한다@Test
@Transactional
public void 출력안되는컬렉션식of(){
//given
biSetting();
Member member1 = new Member();
member1.setName("mem1");
em.persist(member1);//member1도 영속화되어있어야 되는듯
//when
List<Team> list = em.createQuery("select t from Team t where :member1 member of t.members", Team.class).setParameter("member1", member1).getResultList();//주솟값이 다르니 출력이 안됨
//then
for (Team team:list) {
System.out.println(team.getName());
}
}
@Test
@Transactional
public void 출력되는컬렉션식of(){
//given
Member member1 = new Member();
member1.setName("mem1");
Team team1 = new Team();
team1.setName("team1");
team1.addMember(member1);
em.persist(member1);//member1도 영속화되어있어야 되는듯
em.persist(team1);
//when
List<Team> list = em.createQuery("select t from Team t where :member1 member of t.members", Team.class).setParameter("member1", member1).getResultList();
//then
for (Team team:list) {
System.out.println(team.getName());
}
}
select coalesce(m.username, '이름없는회원') from Member m
select nullif(m.username, '관리자') from Member m
select p from Parent p
1) item중에 book, movie를 조회해보자
select i from Item i where type(i) in (Book, Movie)
실제 나가는 sql
select i from Item i where i.dtype in ('B','M')
2) 부모타입을 타입캐스팅해서 사용하기
select i from Item where treat(i as Book).author = '김'
select count(m.id) from Member m //id사용
select count(m) from Member m//직접사용
실제 실행되는 쿼리
select count(m.id) from Member m
select m from Member m where m = :member
실행된 sql
select m from Member m where m.id =:member.id
select m from Member m where m.team = :team
select m from Member m where m.team_id = :team_id
https://data-make.tistory.com/728
https://github.com/Youngerjesus/Querydsl/blob/master/docs/basic.md
잘정리되어있어서 참고했다
오늘은 jpql에 대해서 설명
sql과 비슷한데 sql은 테이블을 대상으로 쿼리를 날리는 언어였다면
jpql은 entity(객체)를 대상으로 쿼리를 날리는 객체지향언어야
jpql을 작성하면 jpa가 알아서 해석해서sql을 dbms로 날려준다. 그래서 dbms에 의존적이지 않다
jpql작성을 도와주는 빌더클래스
빌더클래스란 무엇일까?
페치조인: 연관된 엔티티들을 함께 한번에 조회해오는 조인
조회해와서 이들모두 영속화시킨다(n+1문제도 해결됨)
연관된 애를 한번에 조회해오니까 n+1문제가 해결되지. n+1문제는 연관된 애까지 한번에 조회를 못해왔으니까 쿼리를 더 날리는 상황이니깐
n+1문제란?
team 2가 있고 member가 몇개 있어 그냥 team 을 select해오는건데 team에 연관된 member도 조회해오느라고
지연로딩이든 즉시로딩이든 select member from m.id = ? 을 team개수만큼 실행시키는거지 그래서 n+1문제.
findall을 하면 이 문제가 발생함 근데 findbyid를 하면 연관된 엔티티들을 모두 조인해서 가져온다
findbyid 와 findall의 차이는?
findAll: em.createQuey(select * from Team); -> jpql사용
findById: em.find(Team.class, ${id}); -> jpql을 사용하지 않음
그니까 n+1라는것은 jpql의 문제인것임
em.find(Team.class, id)와 -> 연관된 엔티티는 조인으로 가져옴 -> jpql아님
em.createQuery(select t from Team t where t.id :=id) -> jpql
의 차이는 바로 디비로 조회하러 가느냐 영속성컨텍스트를 들르느냐의 차이
em.find가 jpql이 아닌 이유
em.find는 영컨에서 식별자로 엔티티를 찾는거임 디비에 쿼리를 날리긴하지만 그 쿼리를 우리가 작성하진 않으니
jpql이 아닌 것이다. (이해가 잘 가진 않지만 그런댄다 메서드를 호출하는 목적을 생각해봐라.)
jpql은 쿼리로 엔티티를 가져오는 것
페치조인의 한계
동적쿼리와 정적쿼리
em.createQuery -> 동적쿼리 -> 보통 jpql그대로 사용하지않고 동적쿼리는 쿼리dsl사용
정적쿼리 -> named쿼리
@Entity
@NamedQuery(
name = "Member.findMemberByName",
query = "select m from Member m where m.name = :username"
)
public class Member extends DateMarkable{