console.log("연록")

[JPQL] 파라미터 바인딩, 프로젝션 본문

bone up/JPA

[JPQL] 파라미터 바인딩, 프로젝션

연 록 2022. 5. 30. 02:05
728x90

파라미터 바인딩

 

이름 기준 파라미터

  • 파라미터를 이름으로 구분하는 방법
  • 앞에 ' : ' 사용
String usernameParam = "User1";

TypedQuery <Member> query = 
	em.createQuery("select m from Mmeber m where m.username = :username", Member.class);

query.setParameter("username", usernameParam);
List <Member> resultList = query.getResultList();

':username' 이라는 이름 기준 파라미터를 정의하고 query.setParameter()에서 username이라는 이름으로 파라미터를 바인딩

 

 

위치 기준 파라미터

  • ' ? ' 다음에 위치 값을 주면 됨
  • 위치 값은 1부터 시작
List <Member> members = 
	em.createQuery("select m from Member m where m.username = ?1", Member.class)
    	.setParameter(1, usernameParam)
        .getResultList();

프로젝션

 

  • select 절에 조회할 대성을 지정하는 것을 프로젝션이라 함
  • select {프로젝션 대상} from
  • 프로젝션 대상 : 엔티티, 엠비디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)

 

엔티티 프로젝션

select m from Member m	// 회원
select m.team from Member m	// 팀

영속성 컨텍스트에서 관리

 

 

 

엠베디드 타입 프로젝션

// 잘못된 쿼리(엠베디드 타입인 Address를 조회의 시작점으로 사용함)
String query = "select a from Address a";

// Order 엔티티가 시작점
String query = "select o.address from Order o";
List <Address> addresses = em.createQuery(query, Address.class)
				.getResultList();

임베디드 타입은 엔티티 타입이 아닌 값 타입 → 영속성 컨텍스트에서 관리되지 않음

 

 

 

스칼라 타입 프로젝션

List <String> usernames = em.createQuery("select username from Member m", String.class)
				.getResultList();

영속성 컨텍스트에서 관리

 

 

 

타입별 프로젝션 요약

SELECT m FROM Member m	// 엔티티 프로젝션
SELECT m.team FROM Member m	// 엔티티 프로젝션
SELECT m.address FROM Member m	// 임베디드 타입 프로젝션
SELECT m.username, m.age FROM Member m	// 스칼라 타입 프로젝션
// DISTINCT로 중복 제거

 

 

 

여러 값 조회 프로젝션

  1. Query 타입
  2. Object[] 타입
  3. new 명령어 조회
    • 패키지 명을 포함한 전체 클래스 명 입력
    • 순서와 타입이 일치하는 생성자 필요
Query query = em.createQuery("select m.username, m.age from Member m");
List resultList = query.getResultList();

Iterator iterator = resultList.iterator();
while (iterator.hasNext()) {
	Object [] row = (Object[]) iterator.next();
    String username = (String) row[0];
    Integer age = (Integer) row[1];
}

 Query 타입 

List <Object[]> resultList = em.createQuery("select m.username, m.age from Member m")
			.getResultList();

for (Object [] row : resultList) {
	String username = (String) row[0];
    Integer age = (Integer) row[1];
}

▲ Object[] 타입

List <Object[]> resultList =  
	em.createQuery("select o.member, o.product, o.orderAmount from Order o")
    .getResultList();
    
for (Object[] row : resultList) {
	Member member = (Member) row[0];	// 엔티티
    Product product = (Product) row[1];	// 엔티티
    int orderAmount = (Integer) row[2];	// 스칼라
}

 여러 타입 함께 조회

List <Object[]> resultList = em.createQuery("select m.username, m.age, from Member m")
				.getResultList();

// 객체 변환 작업
List <UserDTO> userDTOs = new ArrayList <UserDTO>();
for (Object [] row : resultList) {
	UserDTO userDTO = new UserDTO((String) row[0], (Integer) row[1]);
    userDTOs.add(userDTO);
}


// UserDTO
public class UserDTO {
	
    private String username;
    private int age;
    
    public UserDTO (String username, int age) {
    	this.username = username;
        this.age = age;
    }
}



// New 명령어 사용
TypedQuery <UserDTO> query = 
	em.createQuery("select new jpabook.jpql.UserDTO(m.username, m.age) from Member m", UserDTO.class);

List <UserDTO> resultList = query.getResultList();

New 명령어 사용