Database ( DB )/JPA, Querydsl

Spring JPA selecting specific columns

노루아부지 2020. 12. 20. 00:17

JPA에서 기본으로 제공하는 findById(), findAll() 등을 사용하면 기본적으로 모든 컬럼을 select합니다.

만약, 특정 컬럼을 구하려고 할 경우 아래와 같이 하면 됩니다.

 

먼저, 아래와 같은 User Entity가 존재한다고 가정합니다.

@Entity
@Getter
@Setter
public class User {
    @Id
    private String userId;
    private String userName;
    private Integer age;
}

 

 

 

1. nativeQuery 사용

import com.example.demo.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface UserRepository extends JpaRepository<User, String> {
    @Query(value = "SELECT user_id, user_name FROM user", nativeQuery = true)
    List<Object[]> selectAllUserId2();
}

nativeQuery 옵션이 true일 경우 @Query에 실제 쿼리문을 사용할 수 있습니다.

단, 이 경우 return되는 값은 User나 UserDto 클래스가 될 수 없고, String, Long 같은 자료형의 배열의 List로 return됩니다.

이것을 test로 만든 코드는 아래와 같습니다.

 

@SpringBootTest
class DemoApplicationTests {

	@Autowired
	UserRepository userRepository;

	@BeforeEach
	void before()  {
		User u1 = new User();
		u1.setUserId("hong");
		u1.setUserName("홍길동");
		u1.setAge(19);
		userRepository.save(u1);

		User u2 = new User();
		u2.setUserId("lim");
		u2.setUserName("임꺽정");
		u2.setAge(29);
		userRepository.save(u2);
	}

	@Test
	void contextLoads() {
		List<Object[]> users = userRepository.selectAllUserId2();

		for (Object[] user : users) {
			System.out.println("userId : " + user[0]);
			System.out.println("userName : " + user[1]);
		}
	}
}

 

위 테스트 코드의 결과는 아래와 같습니다

 

 

 

2. Class의 생성자 사용

import com.example.demo.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface UserRepository extends JpaRepository<User, String> {
    @Query("SELECT new com.example.demo.domain.User(u.userId, u.userName) FROM User u")
    List<User> selectAllUserId();
}

다음과 같이 User Entity의 생성자를 이용하여 일부 데이터를 구할 수 있습니다. 이를 위해서는 userId, userName만 파라메터로 받는 생성자가 존재해야 합니다.

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import javax.persistence.Entity;
import javax.persistence.Id;


@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
public class User {
    @Id
    private String userId;
    private String userName;
    private Integer age;

    public User(String userId, String userName) {
        this.userId = userId;
        this.userName = userName;
    }
}

 

이것을 테스트코드로 만들면 다음과 같습니다.

 

import com.example.demo.domain.User;
import com.example.demo.repository.UserRepository;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.event.annotation.BeforeTestClass;

import java.util.List;

@SpringBootTest
class DemoApplicationTests {

	@Autowired
	UserRepository userRepository;

	@BeforeEach
	void before()  {
		User u1 = new User();
		u1.setUserId("hong");
		u1.setUserName("홍길동");
		u1.setAge(19);
		userRepository.save(u1);

		User u2 = new User();
		u2.setUserId("lim");
		u2.setUserName("임꺽정");
		u2.setAge(29);
		userRepository.save(u2);
	}

	@Test
	void contextLoads1() {
		List<User> users = userRepository.selectAllUserId();

		for(User tmp : users) {
			System.out.println(tmp.toString());
		}
	}
}

 

위 테스트 코드를 실행한 결과는 아래와 같습니다.

 

 

이렇게 age는 null로 출력되는데요 age도 표시하기 싫을 경우 다음과 같이 UserDto를 생성하면 됩니다.

 

@Getter
@Setter
@ToString
@AllArgsConstructor
public class UserDto {
    private String userId;
    private String userName;
}
import com.example.demo.domain.User;
import com.example.demo.domain.UserDto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface UserRepository extends JpaRepository<User, String> {
    @Query("SELECT new com.example.demo.domain.UserDto(u.userId, u.userName) FROM User u")
    List<UserDto> selectAllUserId3();
}

 

 

이것을 테스트 코드를 돌리면 다음과 같습니다.

 

import com.example.demo.domain.User;
import com.example.demo.domain.UserDto;
import com.example.demo.repository.UserRepository;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.event.annotation.BeforeTestClass;

import java.util.List;

@SpringBootTest
class DemoApplicationTests {

	@Autowired
	UserRepository userRepository;

	@BeforeEach
	void before()  {
		User u1 = new User();
		u1.setUserId("hong");
		u1.setUserName("홍길동");
		u1.setAge(19);
		userRepository.save(u1);

		User u2 = new User();
		u2.setUserId("lim");
		u2.setUserName("임꺽정");
		u2.setAge(29);
		userRepository.save(u2);
	}

	@Test
	void contextLoads3() {
		List<UserDto> all = userRepository.selectAllUserId3();

		for(UserDto tmp : all) {
			System.out.println(tmp.toString());
		}
	}
}

 

결과는 다음과 같이 표시됩니다.

 

 

 

 

 

reference

stackoverflow.com/questions/22007341/spring-jpa-selecting-specific-columns

wonwoo.ml/index.php/post/1023

www.appsdeveloperblog.com/specific-columns-jpa-native-query/

728x90
loading