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
www.appsdeveloperblog.com/specific-columns-jpa-native-query/
'Database ( DB ) > JPA, Querydsl' 카테고리의 다른 글
Entity Inheritence in JPA (0) | 2021.08.23 |
---|---|
Spring boot JPA에서 DB 예약어를 column으로 사용하는 방법 (0) | 2021.03.07 |
No identifier specified for entity (0) | 2020.12.19 |
jpa] @CreatedDate annotation이 동작하지 않는 경우 (0) | 2020.12.04 |
querydsl에서 select에 string 사용 (0) | 2019.08.12 |