/* JPQL에서 제공하는 프로젝션을 통해 조회할 값들에 따라 어떤 방식으로 처리할 수 있는지에 대해 살펴본다. */ public class Application {

public static void main(String[] args) {

  /*
   * 프로젝션(projection)
   * SELECT 절에 조회할 대상을 지정하는 것을 프로젝션이라고 한다.
   * (SELECT {프로젝션 대상} FROM)
   *
   * 프로젝션 대상은 4가지 방식이 있다.
   * 1. 엔티티 프로젝션
   *    원하는 객체를 바로 조회할 수 있다.
   *    조회된 엔티티는 영속성 컨텍스트가 관리한다.
   *
   * 2. 임베디드 타입 프로젝션(임베디드 타입에 대한 설명은 MenuInfo 클래스에서 설명)
   *    엔티티와 거의 비슷하게 사용되며 조회의 시작점이 될 수 없다.
   *    엔티티 타입이 아닌 값 타입으로 조회한 임베디드 타입은 영속성 컨텍스트에서 관리되지 않는다.
   *
   * 3. 스칼라 타입 프로젝션
   *    숫자, 문자, 날짜 같은 기본 데이터 타입이다.
   *    스칼라 타입은 영속성 컨텍스트에서 관리되지 않는다.
   *
   * 4. new 명령어를 활용한 프로젝션
   *    다양한 종류의 단순 값들을 DTO로 바로 조회하는 방식으로 new 패키지명.DTO명을 쓰면
   *    해당 DTO로 바로 반환받을 수 있다.
   *    new 명령어를 사용한 클래스의 객체는 엔티티가 아니므로 영속성 컨텍스트에서 관리되지 않는다.
   */
  EntityManager em = getEntityManager();

  /* 1. 엔티티 */

// entityMethod(em);

  /* 2. 임베디드 타입 */

// embeddedMethod(em);

  /* 3. 스칼라 타입 */

// scalarMethod(em);

  /* 4. new 명령어 */
  newMethod(em);

  em.close();

}

private static void entityMethod(EntityManager em) {

  /* 메뉴 엔티티만 가지고 진행 */

// String jpql = "SELECT m FROM SECTION03_MENU m"; // List<Menu> menuList = em.createQuery(jpql, Menu.class).getResultList(); //

// for (Menu menu : menuList) { // System.out.println(menu); // }

  /* 양방향 연관관계에 있는 엔티티들로 진행 */

// String jpql = "SELECT m.category FROM SECTION03_MENUANDCATEGORY m WHERE m.code = 3"; // CategoryAndMenu menu = em.createQuery(jpql, CategoryAndMenu.class).getSingleResult(); //

// System.out.println(menu); }

private static void embeddedMethod(EntityManager em) {

  /*
   * 임베디드 타입을 프로젝션하기 위해서 임베디드 타입(MenuInfo)과
   * 임베디드 타입을 활용하는 엔티티(EmbeddedMenu)를 만들고 아래 예제 작성
   */
  String jpql = "SELECT m.menuInfo FROM SECTION03_EMBEDDEDMENU m";

  /* 임베디드 타입을 프로젝션 했으므로 임베디드 타입이 나오게 된다. */
  List<MenuInfo> menuInfoList = em.createQuery(jpql, MenuInfo.class).getResultList();

  for (MenuInfo menuInfo : menuInfoList) {
     System.out.println(menuInfo);
  }

}