Spring Boot 12일차

김용진·2023년 10월 12일
0

1. JPQL 문법

"select m from Member as m where m.age > 18" 이라는 DB문을 쓸때 자바에서는 무엇을 주의 해야할까?

  • Member : 대소문자 구분을 주의하자. java클래스는 대소문자를 구분하기 때문, 테이블 이름이 아닌, 엔티티 이름을 사용한다.
  • 엔티티 이름을 @Entity(name = "mm") 으로 정해줄 경우, jpql에서도 mm으로 사용한다는 뜻
    그러나 이런방식은 흔히 사용하지않으니 알아만 두자.
    -> JPQL 키워드 : select, from, where 대소문자 구분안함.

1-1. 집합과 정렬

select 
	count(m), 	// 회원 수
	sum(m.age),	// 나이 합
	avg(m.age),	// 평균 나이
	max(m.age),	// 최대 나이
	min(m.age)	// 최소 나이
from Member m

- group by, having
- order by

DB에서 SQL을 쓰던걸 잊지말자.

1-2. TypeQuery, Query

  • TypeQuer : 반환 타입이 명확할 때 사용, 두번째 파라미터에 클래스를 잡아주는걸 볼 수 있다.
	TypeQuery<Member> query =
	em.createQuery("select m from member m", Member.class);
  • Query : 반환 타입이 명확하지 않을 때 사용
 	Query query = 
	em.createQuery("select m.username, m,age from Member m");

1-3. 결과 조회

  • query.getResultList() : 결과가 하나 이상일 때, 리스트 반환
    -> 결과가 없으면 빈 리스트 반환
    -> 빈 collection이 반환되기 때문에 NullPointException에 대한 걱정은 안해도 된다.
  • query.getSingleList() : 결과가 정확히 하나(조심), 단일 객체 반환
    -> 결과가 없으면 : NoResultException
    -> 결과가 둘 이상이면 : NonUniqueResultException 반환

1-4. 파라미터 바인딩

파라미터는 방식에 따라 두가지로 선언하여 바인딩이 가능하다.

  • 이름 기준
	select m from Member m where m.username = :username

	query.setParameter("username", usernameParam);
  • 위치 기준
	select m from Member m where m.username = ?1

	query.setParameter(1, usernameParam);

1-5. 프로젝션

  • select 절에 조회할 대상을 지정하는 것

  • 프로젝션 대상 : 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)

    	- select m from Member m 
    	-> Member 엔티티 조회
    	- select m.team from Member m
    	-> Member와 관련된 team을 가지고 온다.
    	- select m.address from Member m
    	-> 임베디드 타입을 불러온다.
    	- select m.username, m.age from Member m
    	-> 스칼라 타입을 불러온다.

1-6. 여러타입으로 조회

지금까지 지식을 바탕으로 조회하는것을 보자.

  • 프로젝션 타입.
List<Member> result
			= em.createQuery("select m from Member m", Member.class)
			 	.getResultList();
		
		Member findMember = result.get(0);
		findMember.setAge(20);
		/*--------------------------------------------------------*/
		
		/*
		 * jpql입장에서는 select문이 나가지만,실제 sql입장에서는
		 * member와 team을 조인해서 결과를 찾아야 한다.
		 * 근데 join은 실제 sql문과 비슷하게 작성해야한다.
		 */
		List<Team> result2 =
				em.createQuery("select m.team from Member m",Team.class)
				   .getResultList();
		
		
		List<Team> result3 =
				em.createQuery("select t from Member m join m.team t",Team.class)
				   .getResultList();
		
		
		///////////////////////////////////////////////////////////////
		//임베디드 타입
		em.createQuery("select o.address from Order o", Address.class)
	      .getResultList();
		
		// Address 자체는 임베디드 타입일 뿐 엔티티가 아니다.따라서 다음과 같은 코드는 잘못되어있다.
//		em.createQuery("select o.address from Address o ", Address.class)
//		.getResultList();
		
		////////////////////////////////////////////////////////////////
		//스칼라 타입, 리턴타입이 없기 떄문에 두번째 파라미터는 없다.
		em.createQuery("select distinct m.username, m.age from Member m")
		  .getResultList();

1. 타입 미지정, 엔티티 조회

		List resultList = 
				em.createQuery("select m.username, m.age from Member m")
				.getResultList();
		
		Object o = resultList.get(0);
		Object[] result = (Object[])o;
		System.out.println("username :" + result[0]);
		System.out.println("age :" + result[1]);

타입을 지정하지 않았기 때문에 Object로 받아오는것이 보인다. 애플리케이션에서 실행을 한다면

	username :member1
	age :10

결과값을 보내준다. username과 age는 임의로 넣은 값으로 봐주면 될것 같다.

2. 타입지정, 엔티티 조회

		List<Object[]> resultList2 = 
				em.createQuery("select m.username, m.age from Member m")
				.getResultList();
		
		Object[] result2 = resultList2.get(0);
		System.out.println("username :" + result2[0]);
		System.out.println("age :" + result2[1]);

3. 객체 방식 조회

	List<MemberDTO> result3 = 
				em.createQuery("select new com.codingbox.jpql.MemberDTO(m.username, m.age) from Member m")
				.getResultList();
		
		MemberDTO memberDTO = result3.get(0);
		System.out.println("memberDTO : " + memberDTO.getUsername());
		System.out.println("memberDTO : " + memberDTO.getAge());
		
		
		tx.commit();
		em.close();
		emf.close();

MemberDTO 객체를 따로 만들어, 조회하는 방식이다. 가장 권장하는 방식이며, 객체지향방식에 어울리는 코딩이다.

1-7. 페이징 API

  • JPA는 페이지를 다음 두 API로 추상화
  • setFirstResult(int startPoint): 조회 시작 위치(defalut 0부터 시작)
  • setMaxResults(int maxResult) : 조회할 데이터 수
    -> 몇 번째 부터 몇 건을 가지고 올래? 라고 묻는다.
 List<Member> resultList = em.createQuery(jpql,Member.class)
									.setFirstResult(10)
									.setMaxResults(20)
									.getResultList();

페이징처리를 한 구문만 가져왔다.
.setFirstResult(10)를 선언 함으로써 10번째 부터 값을 가져오도록 설정을 해준다.
.setMaxResults(20)를 이용해서 20개의 값만 가져올거라 선언을 해준다.
이처럼 수많은 값들이 있을 경우, 페이징 처리를 통해 필요한 값만 가져올 수 있다.

1-8. 조인

  • 문법이 객체 스타일로 나간다
  • 내부조인
    -> select m from Member m (inner 생략가능) join m.team t
  • 외부 조인
    -> selct t from Meber m left (outer 생략) join m.team t

1-9. 서브쿼리

  • From절의 서브쿼리는 현재 JPQL에서 불가능하다, 조인으로 풀 수 있으면 풀어서 해결하자
profile
메모리폼

0개의 댓글