[Spring_Boot] JPQL 정리

최현석·2022년 12월 12일
0

Spring_Boot

목록 보기
26/31

🧩 프로젝션

  • select 절에 조회할 대상을 지정하는 것
  • select m from Member m
    -> Member 엔티티 조회
  • select m.team from Member m
    -> Member와 관련된 team을 가지고 온다.
  • select m.username, m.age from Member m
    -> Member 엔티티에 있는 username, age를 조회
@Entity
@Getter @Setter
public class Member {

	@Id @GeneratedValue
	private Long id;
	private String username;
	private int age;
	
	@ManyToOne
	@JoinColumn(name = "TEAM_ID")
	private Team team;
}
/////////////////////////////////////////////////

@Entity
@Getter @Setter
public class Team {

	@Id @GeneratedValue
	@Column( name = "TEAM_ID")
	private Long id;
	private String name;
	
	@OneToMany(mappedBy = "team")
	private List<Member> members = new ArrayList<Member>();
}
/////////////////////////////////////////////////

@Entity
@Getter @Setter
@Table(name = "Orders")
public class Order {

	@Id @GeneratedValue
	private Long id;
	private int orderAmount;
	@Embedded
	private Address address;
	
}
/////////////////////////////////////////////////

@Embeddable
@Getter @Setter
public class Address {

	private String city;
	private String street;
	private String zipcode;
	
}

insert

			Member member = new Member();
			member.setUsername("member1");
			member.setAge(10);
			em.persist(member);
			
			em.flush();
			em.clear();

영속성을 비워낸 이후 영속성 컨텍스트 관리

  • result라는 결과값이 select문을 날림으로 인해서 영속성 컨텍스트에 관리가 될까 안될까?
  • update된다 -> 영속성 컨텍스트에서 관리가 된다. (O)
  • update안된다 -> 영속성 컨텍스트에서 관리가 안된다.
			List<Member> result = em.createQuery("select m from Member m",Member.class)
									.getResultList();
			
			
			Member findMember = result.get(0);
			findMember.setAge(20);
			System.out.println(findMember.getAge());

join

		// inner join
		List<Team> result = em.createQuery("select m.team from Member m", Team.class)
								.getResultList();
        // 권장, 의도를 파악하기 쉽다.
		List<Team> result = em.createQuery("select t from Member m join m.team t",
					Team.class).getResultList();

embeded타입 프로젝션 select

			// orders 테이블의 address를 가지고온다
			em.createQuery("select o.address from Order o", Address.class)
				.getResultList();
			
			// 독립적인 entity가 아니라서 테이블처럼 조회해 올 수 없다. 에러!!!
			em.createQuery("select o.address from Address o", Address.class)
				.getResultList();
			// 중복되는 이름없이 사용, 반환타입이 명확하지 않아 2번째 파라미터 지우기(Address.class)
			em.createQuery("select distinct m.username , m.age from Member m")
				.getResultList();
    1. orders라는 테이블에서 그 안에있는 address 라는 컬럼만을 조회

결과 값을 받아오는 방법

			// 1번 방법
			List resultList =  em.createQuery("select m.username , m.age from Member m")
							.getResultList();
			
			// 타입(String, int)을 지정하지 못하니까 object로 받아온다.
			Object o = resultList.get(0);
			Object[] result = (Object[]) o;
			System.out.println("username = " + result[0]);
			System.out.println("age = " + result[1]);
			
			// 2번 방법
			List<Object[]> resultList =  em.createQuery("select m.username , m.age from Member m")
									.getResultList();
			Object[] result = resultList.get(0);
			System.out.println("username = " + result[0]);
			System.out.println("age = " + result[1]);			
  			
			// 3번 방법, 가장 많이 사용되는 방법
			List<MemberDTO> result 
				=  em.createQuery("select new com.koreait.jpql.MemberDTO( m.username , m.age ) from Member m")
					.getResultList();
			
			MemberDTO memberDTO = result.get(0);
			System.out.println("username : " + memberDTO.getUsername());
			System.out.println("age : " + memberDTO.getAge());
  • 3번 방법 DTO설정, 특정 결과값만을 따로 받아오는 DTO가 필요시 사용
@Getter @Setter @ToString
public class MemberDTO {

	private String username;
	private int age;
	
	public MemberDTO(String username, int age) {
		super();
		this.username = username;
		this.age = age;
	}
}

🧩 페이징 처리

  • setFirstResult(int startPoint) : 조회 시작 위치(0부터 시작)
  • setMaxResults(int maxResults) : 조회할 데이터 수
  • 몇 번째부터 몇 개 가지고 올래?
	for (int i = 0; i < 100; i++) {
				Member member = new Member();
				member.setUsername("member" + i);
				member.setAge(i);
				em.persist(member);

			}
			
			em.flush();
			em.clear();
			
			// 페이징 처리
			String jpql = "select m from Member m order by m.id";
			List<Member> resultList = em.createQuery(jpql, Member.class)		
										.setFirstResult(30)
										.setMaxResults(10)
										.getResultList();
			
			System.out.println("result.size : " + resultList.size());	
			
			for(Member member1 : resultList) {
				System.out.println("member1 = " +member1.toString());
			}

🧩 JPA서브쿼리 한계

  • where, having 절에서 사용가능 -> JPA 표준 스펙
  • select 절에서도 가능 -> 하이버네이트에서 지원
  • from 절의 서브쿼리는 현재 JPQL에서 불가능
			// 조인 : inner join -> inner는 생략 가능
		String sql = "select m from Member m inner join m.team t where 	t.name = :teamName";
		List<Member> resultList = em.createQuery(sql, Member.class)
										.getResultList();
			
		// left outer join
		String sql = "select m from Member m left outer join m.team t";
		List<Member> resultList = em.createQuery(sql, Member.class)
				.getResultList();

			// subQuery
			String sql = "select m from Member m where m.age > (select avg(m2.age) from Member m2)";
			List<Member> resultList = em.createQuery(sql, Member.class)
										.getResultList();
  • 1번
  • 2번
  • 3번

0개의 댓글